2010-08-25 9 views
9

spring documentation regarding testing में, यह कहा गया है:वसंत के साथ परीक्षण करते समय झूठी सकारात्मकताओं से बचने के लिए पूर्व फ़्लशिंग की आवश्यकता पर स्पष्टीकरण की आवश्यकता है?

झूठे सकारात्मक बचें परीक्षण जब ORM कोड

जब आप इस तरह के जेपीए या हाइबरनेट के रूप में एक ORM ढांचे से जुड़े कोड का परीक्षण, परीक्षण भीतर अंतर्निहित सत्र फ्लश विधियां जो सत्र की स्थिति अद्यतन करती हैं। ओआरएम फ्रेमवर्क के अंतर्निहित सत्र को फ्लश करने में विफल होने से झूठी पॉजिटिव उत्पन्न हो सकती है: आपका परीक्षण पास हो सकता है, लेकिन एक ही कोड लाइव, उत्पादन वातावरण में अपवाद फेंकता है। में हाइबरनेट-आधारित उदाहरण परीक्षण केस के बाद, एक विधि एक झूठी सकारात्मक प्रदर्शित करती है और अन्य विधि सत्र को फ़्लश करने के के परिणामों को सही ढंग से प्रदर्शित करती है।

क्या कोई समझा सकता है कि मुझे फ्लश कॉल करने की आवश्यकता क्यों है?

उत्तर

3

ठीक है, आप वास्तव में दिलचस्प हिस्सा है, उदाहरण के छोड़ दिया :) संदेश यह है:

// ... 

@Autowired 
private SessionFactory sessionFactory; 

@Test // no expected exception! 
public void falsePositive() { 
    updateEntityInHibernateSession(); 
    // False positive: an exception will be thrown once the session is 
    // finally flushed (i.e., in production code) 
} 

@Test(expected = GenericJDBCException.class) 
public void updateWithSessionFlush() { 
    updateEntityInHibernateSession(); 
    // Manual flush is required to avoid false positive in test 
    sessionFactory.getCurrentSession().flush(); 
} 

// ... 

क्या इस उदाहरण को वर्णन करने की कोशिश करता है कि जब तक आप वास्तव में flush सत्र (उर्फ प्रथम स्तर कैश) के लिए डेटाबेस के साथ मेमोरी में बदलावों को सिंक करें, आप वास्तव में डेटाबेस एकीकरण का परीक्षण नहीं कर रहे हैं और वास्तविक अनुमानित व्यवहार का परीक्षण नहीं कर सकते हैं या किसी समस्या को याद नहीं कर सकते हैं।

उदाहरण के लिए, डेटाबेस एक बाधा उल्लंघन कहने के कारण त्रुटि लौटा सकता है, और यदि आप डेटाबेस को हिट नहीं करते हैं, तो आप इस सही व्यवहार को प्रदर्शित नहीं करेंगे, जैसा ऊपर falsePositive() परीक्षण विधि में है। यह परीक्षण विधि विफल होनी चाहिए, या अपवाद की उम्मीद है लेकिन बस पास हो जाएगी। दूसरी ओर, फ्लश के साथ अन्य परीक्षण विधि वास्तविक व्यवहार का परीक्षण करती है। इसलिए flush की आवश्यकता है।

+0

पास्कल, धन्यवाद। यहां सिफारिश क्या है? फ्लश() किसी भी सहेजने के बाद और पहले स्तर के कैश से बचें जब प्रदर्शन किसी समस्या का अधिक नहीं है? और क्या हमें विधि कॉल के बाहर या यहां तक ​​कि अंदर के परीक्षण के तहत विधि को कॉल करने के बाद फ्लश करना चाहिए? कितना भ्रमित! – JavaRocky

1

वसंत दस्तावेज गलत अवधारणा का उपयोग करता है। यह स्पष्ट किया गया है

लेकिन एक ही कोड एक जीवित, उत्पादन वातावरण में एक अपवाद फेंकता

यहाँ चला जाता है wikipedia

प्रकार द्वितीय त्रुटि, यह भी एक "त्रुटि के रूप में जाना दूसरी तरह का ", एक β त्रुटि, या" झूठी नकारात्मक ": वास्तव में सत्य नहीं होने पर एक शून्य परिकल्पना को अस्वीकार करने में विफल होने की त्रुटि। इसका एक उदाहरण होगा यदि एक परीक्षण से पता चलता है कि एक महिला गर्भवती नहीं है, जब वास्तव में, वह है।

आप स्प्रिंग द्वारा प्रदान की नमूना देखते हैं, तो उत्पादन वातावरण एक अपवाद (ए GenericJDBCException), फेंकता है, लेकिन यह पता लगाया नहीं गया है। देखने के लिए, आपको कुछ ORM प्रदाता का उपयोग करते समय अंतर्निहित प्रतिबद्धता पर कॉल करना होगा।

XUnit टेस्ट पैटर्न परिभाषा

एक situantion जिसमें एक परीक्षण में सफ़ल भले ही परीक्षण के तहत सिस्टम ठीक से काम नहीं कर रहा।

तो सही अवधारणा falseNegative @Transactional साथ

@Test // no expected exception! 
public void falseNegative() { 
1

टिप्पणी करना स्प्रिंग परीक्षण है सुविधाजनक है, लेकिन यह कैसे नहीं अपने उत्पादन कोड निष्पादित किया जाएगा है। @Transactional एनोटेशन आपकी टेस्ट विधि चलाने से पहले एक लेनदेन शुरू करेगा और परीक्षण विधि समाप्त होने पर इसे वापस रोल करेगा।

जबकि प्रतिबद्धता फ्लश से पहले होती है, रोल-बैक नहीं होता है, इसलिए मैन्युअल फ्लश एक सुरक्षा-तंत्र है यह सुनिश्चित करने के लिए कि सभी इकाई परिवर्तनों को SQL कथन में अनुवादित किया जाता है।

एक और अधिक उचित डिजाइन इस तरह स्पष्ट रूप से लेन-देन सीमाओं आकर्षित करने के लिए किया जाएगा:

@Test 
public void testRootObjects() { 

    final Company newCompany = new Company(); 
    newCompany.setName("TV Company"); 

    final Long companyId = transactionTemplate.execute(new TransactionCallback<Long>() { 
     @Override 
     public Long doInTransaction(TransactionStatus transactionStatus) { 
      entityManager.persist(newCompany); 
      return newCompany.getId(); 
     } 
    }); 
    Company detachedCompany = transactionTemplate.execute(new TransactionCallback<Company>() { 
     @Override 
     public Company doInTransaction(TransactionStatus transactionStatus) { 
      Company attachedCompany = entityManager.find(Company.class, companyId); 
      assertEquals(newCompany, attachedCompany); 
      assertEquals(newCompany.hashCode(), attachedCompany.hashCode()); 
      return attachedCompany; 
     } 
    }); 
    assertEquals(newCompany, detachedCompany); 
    assertEquals(newCompany.hashCode(), detachedCompany.hashCode()); 
} 

TransactionTemplate तो मैनुअल flushes के लिए कोई आवश्यकता नहीं है अपने कोड के लिए प्रतिबद्ध होगा।

यदि आप अपने इंटरफ़ेस के माध्यम से @ ट्रांसेक्शनल सेवा विधियों को कॉल करते हैं, तो आपको लेन-देन की आवश्यकता नहीं होगी, क्योंकि आप स्प्रिंग प्रॉक्सी को कॉल कर रहे हैं, जो ट्रांज़ेक्शनइंटरसेप्टर को कॉल करेगा (माना जाता है कि आपने स्प्रिंग को ट्रांजैक्शन एनोटेशन से अवगत कराया था:) इसलिए लेनदेन आपकी ओर से शुरू/प्रतिबद्ध किया जाएगा।

0

क्या किसी ने एनोटेशन @ ट्रान्सएक्शन कॉन्फ़िगरेशन के साथ जांच की है? यदि आप अपने प्रोजेक्ट में संचालित @ ट्रांसेक्शन एनोटेशन का उपयोग कर रहे हैं, तो आप अपने टेस्ट केस में @ ट्रांज़ेक्शन कॉन्फ़िगरेशन (डिफॉल्ट रोलबैक = झूठी, लेनदेन प्रबंधक = "आपका ट्रांज़ेक्शन मैनेजर") सेट कर सकते हैं, उम्मीद है कि यह आपकी मदद करेगा।

संबंधित मुद्दे