2013-06-10 4 views
6

हम मॉकिटो के साथ वास्तव में बुरा समस्या में आए।मॉकिटो: यदि मॉक को पारित तर्क संशोधित किया गया है तो क्या होगा?

कोड:

public class Baz{ 
    private Foo foo; 
    private List list; 

    public Baz(Foo foo){ 
     this.foo = foo; 
    } 

    public void invokeBar(){ 
     list = Arrays.asList(1,2,3); 
     foo.bar(list); 
     list.clear(); 
    } 

} 


public class BazTest{ 

    @Test 
    void testBarIsInvoked(){ 
     Foo mockFoo = mock(Foo.class); 
     Baz baz = new Baz(mockFoo);   
     baz.invokeBar(); 
     verify(mockFoo).bar(Arrays.asList(1,2,3)); 
    } 
} 

इस कारण त्रुटि संदेश की तरह:

Arguments are different! Wanted: 
foo.bar([1,2,3]); 
Actual invocation has different arguments: 
foo.bar([]); 

क्या बस हो गया:

Mockito रिकॉर्ड list बल्किकी प्रतिलिपि से संदर्भ, इसलिए मैकिटो के ऊपर दिए गए कोड में संशोधित संस्करण (खाली सूची, []) के बजाय वास्तव में आवंटन ([1,2,3]) के दौरान पारित किए गए कोड के विरुद्ध सत्यापित किया गया है!

प्रश्न:

इस समस्या का किसी भी सुंदर और स्वच्छ समाधान नीचे की तरह एक रक्षात्मक नकल कर के अलावा अन्य है (जो वास्तव में मदद करता है, लेकिन हम इस समाधान पसंद नहीं है)?

public void fun(){ 
     list = Arrays.asList(1,2,3); 
     foo.bar(new ArrayList(list)); 
     list.clear(); 
    } 

हम सही उत्पादन कोड को संशोधित नहीं करना चाहती और इसके प्रदर्शन को कम केवल परीक्षण के साथ तकनीकी समस्या को ठीक करने के लिए।

मैं इस प्रश्न को यहां पूछ रहा हूं क्योंकि यह संभवतः मॉकिटो के साथ आम समस्या है। या हम बस कुछ गलत करते हैं?

पीएस। यह वास्तविक कोड नहीं है इसलिए कृपया यह न पूछें कि हम एक सूची क्यों बनाते हैं और फिर इसे साफ़ करते हैं। वास्तविक कोड में हमें कुछ ऐसा करने की वास्तविक आवश्यकता है :-)।

+0

क्या आप वास्तव में एक ही तर्क वर्ग के _ अलग उदाहरण_ पर सत्यापित करते हैं? – fge

+0

@fge हां, मेरे पास टेस्ट कोड में मूल उदाहरण तक कोई पहुंच नहीं है इसलिए मुझे अपेक्षित सामग्री के साथ परीक्षण में तर्क का एक नया उदाहरण बनाना होगा। –

+0

फिर मेरा उत्तर देखें – fge

उत्तर

11

यहां समाधान एक अनुकूलित उत्तर का उपयोग करना है। दो कोड नमूने: पहला परीक्षण कक्षाओं का उपयोग किया जाता है, दूसरा परीक्षण है।

सबसे पहले, परीक्षण कक्षाएं:

private interface Foo 
{ 
    void bar(final List<String> list); 
} 

private static final class X 
{ 
    private final Foo foo; 

    X(final Foo foo) 
    { 
     this.foo = foo; 
    } 

    void invokeBar() 
    { 
     // Note: using Guava's Lists here 
     final List<String> list = Lists.newArrayList("a", "b", "c"); 
     foo.bar(list); 
     list.clear(); 
    } 
} 

परीक्षण करने के लिए पर:

@Test 
@SuppressWarnings("unchecked") 
public void fooBarIsInvoked() 
{ 
    final Foo foo = mock(Foo.class); 
    final X x = new X(foo); 

    // This is to capture the arguments with which foo is invoked 
    // FINAL IS NECESSARY: non final method variables cannot serve 
    // in inner anonymous classes 
    final List<String> captured = new ArrayList<String>(); 

    // Tell that when foo.bar() is invoked with any list, we want to swallow its 
    // list elements into the "captured" list 
    doAnswer(new Answer() 
    { 
     @Override 
     public Object answer(final InvocationOnMock invocation) 
      throws Throwable 
     { 
      final List<String> list 
       = (List<String>) invocation.getArguments()[0]; 
      captured.addAll(list); 
      return null; 
     } 
    }).when(foo).bar(anyList()); 

    // Invoke... 
    x.invokeBar(); 

    // Test invocation... 
    verify(foo).bar(anyList()); 

    // Test arguments: works! 
    assertEquals(captured, Arrays.asList("a", "b", "c")); 
} 
बेशक

, इस तरह के एक परीक्षण लिखने के लिए सक्षम होने के लिए जरूरी है कि आप अपने "बाहरी में इंजेक्षन करने में सक्षम हैं ऑब्जेक्ट "पर्याप्त राज्य ताकि परीक्षण सार्थक हो ... यहां यह अपेक्षाकृत आसान है।

+0

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

+0

आह ठीक है। तब मेरे पास एक और समाधान है! – fge

+0

मेरा जवाब देखें। परीक्षण किया और यह काम करता है! – fge

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

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