2012-02-09 10 views
10

मैं जावा अनुप्रयोग विकसित कर रहा हूं जिसमें कई जटिल हाइबरनेट मानदंड प्रश्न हैं। मैं यह मानदंडों का परीक्षण करना चाहता हूं कि वे सही चुन रहे हैं, और केवल सही, वस्तुएं। इसके लिए एक दृष्टिकोण, निश्चित रूप से, एक इन-मेमोरी डेटाबेस (उदा। एचएसक्यूएल) स्थापित करना है और, प्रत्येक परीक्षण में, मानदंडों का उपयोग करके उस डेटाबेस में एक राउंड ट्रिप करें और फिर जोर दें कि क्वेरी परिणाम मेरी अपेक्षाओं से मेल खाते हैं।किसी भी डेटाबेस का उपयोग किए बिना हाइबरनेट मानदंड क्वेरी का परीक्षण कैसे करें?

लेकिन मैं एक आसान समाधान की तलाश में हूं, क्योंकि हाइबरनेट मानदंड केवल जावा ऑब्जेक्ट्स के बारे में तार्किक भविष्यवाणियों का एक विशेष प्रकार है। इस प्रकार वे, सिद्धांत रूप में, किसी भी डेटाबेस तक पहुंच के बिना परीक्षण किया जा सकता है।

InMemoryCriteria criteria = InMemoryCriteria.forClass(Cat.class) 
    .add(Restrictions.like("name", "Fritz%")) 
    .add(Restrictions.or(
     Restrictions.eq("age", new Integer(0)), 
     Restrictions.isNull("age"))) 

assertTrue(criteria.apply(new Cat("Foo", 0))) 
assertTrue(criteria.apply(new Cat("Fritz Lang", 12))) 
assertFalse(criteria.apply(new Cat("Foo", 12))) 

मापदंड इस तरह उत्पादन कोड में इस्तेमाल किया जा सकता है:

class Cat { 
    Cat(String name, Integer age){ 
     this.name = name; 
     this.age = age; 
    } 
    ... 
} 

मैं मापदंड प्रश्नों बनाने के लिए कुछ इस तरह करते हैं, चाहते हैं: उदाहरण के लिए, यह सोचते हैं कि वहाँ एक इकाई Cat कहा जाता है कि :

criteria.getExecutableCriteria(session); //similar to DetachedCriteria 

क्या कोई जावा लाइब्रेरी है जो इस तरह की परीक्षा संभव बनाती है?

उत्तर

15

आप मॉकिटो जैसे एक मॉकिंग फ्रेमवर्क का उपयोग सभी प्रासंगिक हाइबरनेट वर्गों को नकल करने और इन मोजे के अपेक्षित व्यवहार को परिभाषित करने के लिए कर सकते हैं।

बहुत सारे कोड की तरह लगता है, लेकिन चूंकि हाइबरनेट मानदंड एपीआई एक धाराप्रवाह इंटरफेस है, Criteria के सभी तरीके Criteria पर एक नया उदाहरण लौटाते हैं। तो नकली व्यवहार को परिभाषित करना जो सभी परीक्षणों के लिए आम है, सरल है। यहाँ Mockito

@Mock 
private SessionFactory sessionFactory; 

@Mock 
Session session; 

@Mock 
Criteria criteria; 

CatDao serviceUnderTest; 

@Before 
public void before() 
{ 
    reset(sessionFactory, session, criteria); 
    when(sessionFactory.getCurrentSession()).thenReturn(session); 
    when(session.createCriteria(Cat.class)).thenReturn(criteria); 
    when(criteria.setFetchMode(anyString(), (FetchMode) anyObject())).thenReturn(criteria); 
    when(criteria.setFirstResult(anyInt())).thenReturn(criteria); 
    when(criteria.setMaxResults(anyInt())).thenReturn(criteria); 
    when(criteria.createAlias(anyString(), anyString())).thenReturn(criteria); 
    when(criteria.add((Criterion) anyObject())).thenReturn(criteria); 

    serviceUnderTest = new CatDao(sessionFactory); 
} 

Criteria नकली वापसी की सभी तरीकों नकली फिर से उपयोग एक उदाहरण है।

एक ठोस परीक्षण में आप ArgumentCaptor और verify कथन का उपयोग करेंगे ताकि मैक Criteria पर क्या हुआ।

@Test 
public void testGetCatByName() 
{ 
    ArgumentCaptor<Criterion> captor = ArgumentCaptor.forClass(Criterion.class); 

    serviceUnderTest.getCatByName("Tom"); 

    // ensure a call to criteria.add and record the argument the method call had 
    verify(criteria).add(captor.capture()); 

    Criterion criterion = captor.getValue(); 

    Criterion expectation = Restrictions.eq("name", "Tom"); 

    // toString() because two instances seem never two be equal 
    assertEquals(expectation.toString(), criterion.toString()); 
} 

समस्या मैं unitests इस तरह से देखते हैं कि वे परीक्षण के अंतर्गत वर्ग के बारे में उम्मीदों का एक बहुत लागू है। यदि आप ब्लैकबॉक्स के रूप में serviceUnderTest के बारे में सोचते हैं, तो आप यह नहीं जान सकते कि यह बिल्ली वस्तु को नाम से कैसे प्राप्त करता है। यह मानदंड या = के बजाय 'IN' का भी उपयोग कर सकता है, इसके बाद यह Example मानदंड का उपयोग कर सकता है। या यह एक देशी एसक्यूएल क्वेरी निष्पादित कर सकता है।

+4

उत्तर देने के लिए धन्यवाद! लेकिन, जैसा कि आप इंगित करते हैं, इस तरह का परीक्षण सत्यापित करता है कि वर्ग * लागू * कैसे है, यह नहीं कि * व्यवहार * कैसे किया जाता है। इसके अलावा, यह परीक्षण किसी अन्य सेवा पर केंद्रित है, जो मानदंडों का उपयोग करता है। यद्यपि यह निश्चित रूप से कार्यक्षमता का एक महत्वपूर्ण टुकड़ा है, यह परीक्षण करने के लिए अपेक्षाकृत आसान होना चाहिए (इंटरफेस के सही उपयोग के साथ कक्षाओं को डीकॉप्लिंग करके, जिम्मेदारियों को अलग करना आदि)। यहां, मैं मानदंड वस्तु का परीक्षण करने में अधिक रुचि रखता हूं। –

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