2011-12-04 8 views
5

मैं विशिष्ट आदेश को सत्यापित करना चाहता हूं जिसमें पात्र यह सुनिश्चित करने के लिए कि वे खराब नहीं हो रहे हैं। मैंने इसे InOrder का उपयोग करके लिखने की कोशिश की लेकिन ऐसा लगता है कि यह काम नहीं करता है, या कम से कम मॉकिटो 1.8.5 में।उसी तर्क के साथ कॉल के विशिष्ट क्रम के लिए मॉकिटो में परीक्षण कैसे करें?

@Test 
public void inOrderTest() throws IOException{ 
    final String message = "Hello World!\n"; 

    for(char c : message.toCharArray()) 
     mockWriter.write(c); 

    final InOrder inOrder = inOrder(mockWriter); 
    for(char c : message.toCharArray()) 
     inOrder.verify(mockWriter).write(c); 
    inOrder.verifyNoMoreInteractions(); 
} 

परीक्षण ऊपर संदेश के साथ विफल रहता है:

Verification in order failure: 
mockWriter.write(108); 
Wanted 1 time: 
-> at  org.bitbucket.artbugorski.brainfuj.interpreter.InterpreterTest.inOrderTest(InterpreterTest.java:62) 
But was 3 times. Undesired invocation: 
-> at org.bitbucket.artbugorski.brainfuj.interpreter.InterpreterTest.inOrderTest(InterpreterTest.java:58) 

एक है कि के लिए एक Mockito परीक्षण कैसे लिख सकता हूँ करता है?


संपादित करें: क्रम में http://code.google.com/p/mockito/issues/detail?id=296

उत्तर

19

पिछले उत्तरदाताओं से मेरी माफ़ी; लेकिन मेरी राय में, उत्तर का उपयोग करके मॉकिटो के मूलभूत विचारों में से एक के चेहरे में थोड़ा सा उड़ जाता है, अर्थात् कि स्टबिंग और सत्यापन दो पूरी तरह अलग प्रक्रियाएं हैं। मॉकिटो में सत्यापन के लिए स्टबिंग और फीचर्स की विशेषताएं हैं, और मॉकिटो के निर्माताओं ने दो अलग रखने का प्रयास किया है। जवाब स्टबिंग के लिए हैं; और जबकि कुछ ऐसे मामले हैं जहां उत्तर सत्यापित करने का सबसे अच्छा तरीका है, मुझे विश्वास नहीं है कि यह उनमें से एक है।

मैं उत्तर के बजाय एक ArgumentCaptor का उपयोग करूंगा। मैं टेस्ट क्लास में इस तरह की एक विधि लिखूंगा, फिर इसे "हैलो वर्ल्ड" के साथ तर्क के रूप में बुलाऊंगा। ध्यान दें कि मैंने इसका परीक्षण नहीं किया है, इसलिए इसमें टाइपो हो सकते हैं।

private void verifyCharactersWritten(String expected){ 
    ArgumentCaptor<Character> captor = ArgumentCaptor.forClass(Character.class); 
    verify(mockWriter, times(expected.length())).write(captor.capture()); 
    assertEquals(Arrays.asList(expected.toCharArray()), captor.getAllValues()); 
} 

उम्मीद है कि इससे मदद मिलती है।

+0

Slick। मुझे तर्क कैप्चर की उस विशेषता के बारे में पता नहीं था। –

+0

कभी-कभी परिणाम/आउटपुट/परिणाम (यदि यह संभव हो) की जांच करने के लिए आसानी से इस टेस्ट कोड को पढ़ें। मेरा मतलब है कि अगर हम जानते हैं कि इसे हमें वापस करना चाहिए: "कुछ डिंग हमें अपेक्षित तर्कों के लिए" उम्मीद थीं। – ses

4

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

assertThat(stringWriter.toString(), equalTo(message)); 

लग रहा है, सब मेरा सुझाव कर सकते हैं Mockito कोड की खुदाई वहाँ ऐसा और संभवतः बनाने के लिए कोई तरीका है देखने के लिए है यह देखने के लिए कि वे इसके बारे में क्या कहते हैं, एक बग रिपोर्ट दर्ज करना।

+0

मैं तो मैं एक आभासी मशीन/दुभाषिया लिख ​​रहा हूँ/O में एक चरित्र होता है एक समय, पूरे संदेश की कोई धारणा नहीं है, केवल stdout पर मुद्रित व्यक्तिगत वर्णों की एक श्रृंखला है। मैं यह सुनिश्चित करने की कोशिश कर रहा हूं कि उन्हें प्रिंट करने के दौरान मैं कुछ भी भ्रष्ट नहीं कर रहा हूं (हाँ, मैं अपनी आंतरिक मेमोरी लागू कर रहा हूं)। जिस संदेश को मैं सत्यापित करने की कोशिश कर रहा हूं वह है "हैलो वर्ल्ड" इसलिए मुझे नहीं लगता कि यह जांचने के लिए अधिक है कि इस तरह का एक संदेश चरित्र द्वारा चरित्र सही ढंग से मुद्रित किया जा सकता है। :) – ArtB

+1

नमस्ते, ठीक है अगर यह परीक्षण महत्वपूर्ण है, यानी आपको जो भी मिल रहा है उसका परीक्षण करना चाहिए, मैं @Ryan से सहमत हूं, आपको आउटपुट बनाम इनपुट की तुलना करना चाहिए। अपने लेखक को दबाते समय, एक कस्टम उत्तर का उपयोग करें जो चार्ट को सामान्य 'स्ट्रिंगबिल्डर' में जोड़ देगा, फिर इसे हमारे 'हैलो वर्ल्ड "इनपुट से तुलना करें। वैकल्पिक रूप से आप शायद एक कस्टम matcher लिख सकते हैं; कुछ 'inOrder.verify (mockWriter, times (11))। लिखो (charsThatMatchInOrder ("हैलो वर्ल्ड")); ', ** हालांकि स्ट्रिंग में बदलाव होने पर यह परीक्षण आसानी से टूट सकता है! ** – Brice

+0

@ ब्रिस अच्छी तरह से कोड स्निपेट नकली/व्याख्या की जा रही है परीक्षण इनपुट का हिस्सा है, इसलिए यदि यह बदलता है तो यह उम्मीद की जाती है कि परीक्षण विफल हो जाएगा। – ArtB

0

मैं वर्तमान में कस्टम उत्तर के साथ इस पर हैक कर रहा हूं।

final List<Integer> writtenChars = new ArrayList<>(); 
willAnswer(
     new Answer(){ 
      @Override 
      public Object answer(final InvocationOnMock invocation)throws Throwable { 
       final int arg = (int) invocation.getArguments()[0]; 
       writtenChars.add(arg); 
       return null; 
      } 
     } 
    ).given(mockWriter).write(anyInt()); 

फिर वांछित तरीकों को चलाने के बाद मैं सूची के खिलाफ अपेक्षित स्ट्रिंग के खिलाफ परीक्षण करता हूं। ब्राईस आप के लिए क्षमा याचना:

final Iterator<Integer> writtenCharItr = writtenChars.iterator(); 
for(int charInt : "Hello World!\n".toCharArray()) 
    assertThat( charInt, is(writtenCharItr.next()) ); 
assertThat("There are no more chars.", writtenCharItr.hasNext(), is(false)); 
verify(mockWriter).flush(); 

इस हालांकि अगर तुम जब तक आप सूची आदि


संपादित करें जो विधि बुला लिया गया में रिकॉर्ड एक बार विधि कॉल की तुलना में अधिक में रुचि रखते हैं काम नहीं करेगा लगता है कि List के बजाय StringBuilder का उपयोग कर स्वतंत्र रूप से और बेहतर को छोड़कर स्वतंत्र रूप से और बेहतर छोड़कर इस समाधान में आ गया है, हालांकि एक सामान्य मामले के लिए एक सूची बेहतर काम करती है।

+0

मैं क्या सोच रहा था ... एक ArgumentCaptor बेहतर तरीका है, यह मूल रूप से करता है कि यह कस्टम जवाब क्या कर रहा है। कई तरीकों से डेविड की प्रतिक्रिया बहुत अधिक सही है। – Brice

2

कारण मॉकिटो इस तरह काम करता है क्रम में सत्यापन और नियमित सत्यापन के बीच स्थिरता है। दूसरे शब्दों, अगर हमने इसे इस तरह लागू नहीं किया है तो एपीआई एक अलग तरीके से आश्चर्यजनक होगा :) आप सभ्य एपीआई बनाने की कोशिश करते समय व्यापार बंद कर देते हैं।

तो ... उत्तर। सबसे पहले, आपको टेस्ट कोड में लूप (या सशर्त) जैसे बयान से बचना चाहिए। कारण है कि आप टेस्ट कोड स्पष्टता और रखरखाव के लिए बहुत कुछ परवाह करते हैं! =)

यदि हम परीक्षण से लूप को हटाते हैं तो हमारे पास अब उपयोग का कोई मामला नहीं है, हालांकि ... उपयोग के मामले में इसका उत्तर देना मुश्किल है। डेविड का ArgumentCaptor एक बुरा विचार नहीं हो सकता है।

आशा है कि मदद करता है!

+0

मैं असहमत हूं। मैं लूप को अनलोल कर सकता हूं और एक ही समस्या होगी। मैं इसे एक तथ्य के लिए जानता हूं क्योंकि मैंने इसे डीबग करने का प्रयास करते समय किया था। दूसरा, अगर यह इनऑर्डर कहलाता है लेकिन यह बिल्कुल नहीं बता सकता कि कॉल किस क्रम में किए गए थे, यह नहीं है कि कम से कम आश्चर्य के सिद्धांत का चमकदार उल्लंघन? – ArtB

0

यह एक अजीब परीक्षण है, लेकिन फिर भी, इसे मॉकिंग एपीआई द्वारा समर्थित किया जाना चाहिए। मुझे विश्वास है कि को मॉकिटो द्वारा समर्थित किया जा सकता है, क्योंकि अन्य मॉकिंग एपीआई इसका समर्थन करते हैं।

साथ Unitils नकली:

Mock<Writer> mockWriter; 

@Test 
public void inOrderTest() throws Exception { 
    Writer writer = mockWriter.getMock(); 
    final String message = "Hello World!\n"; 

    for (char c : message.toCharArray()) 
     writer.write(c); 

    for (char c : message.toUpperCase().toCharArray()) 
     mockWriter.assertInvokedInSequence().write(c); 
    MockUnitils.assertNoMoreInvocations(); 
} 

या JMockit (मेरे अपने उपकरण) के साथ:

@Test 
public void inOrderTest(final Writer mockWriter) throws Exception { 
    final String message = "Hello World!\n"; 

    for (char c : message.toCharArray()) 
     mockWriter.write(c); 

    new FullVerificationsInOrder() {{ 
     for (char c : message.toCharArray()) 
      mockWriter.write(c); 
    }}; 
} 
संबंधित मुद्दे