मॉकिटो: doAnswer Vs तत्कालीन


124

मैं मॉकिटो का उपयोग सेवा के लिए बाद में इकाई परीक्षण में कर रहा हूं। मैं उलझन में हूँ जब उपयोग करने के लिए doAnswerबनाम thenReturn

क्या कोई मुझे विस्तार से मदद कर सकता है? अब तक, मैंने इसके साथ प्रयास किया है thenReturn

जवाबों:


167

जब आप किसी विधि कॉल का मजाक उड़ाते हैं तो आपको वापसी मूल्य का उपयोग करना चाहिए thenReturnया doReturnजब आप जानते हैं। यह परिभाषित मान वापस किया जाता है जब आप नकली विधि को लागू करते हैं।

thenReturn(T value) विधि के वापस आने पर लौटाया जाने वाला मान सेट करता है।

@Test
public void test_return() throws Exception {
    Dummy dummy = mock(Dummy.class);
    int returnValue = 5;

    // choose your preferred way
    when(dummy.stringLength("dummy")).thenReturn(returnValue);
    doReturn(returnValue).when(dummy).stringLength("dummy");
}

Answer इसका उपयोग तब किया जाता है जब आपको एक नकली विधि लागू करने पर अतिरिक्त कार्रवाई करने की आवश्यकता होती है, उदाहरण के लिए जब आपको इस विधि कॉल के मापदंडों के आधार पर रिटर्न मान की गणना करने की आवश्यकता होती है।

doAnswer()जब आप एक शून्य विधि को जेनेरिक के साथ चिपकाना चाहते हैं, तब उपयोग करें Answer

उत्तर एक क्रिया निर्दिष्ट करता है जिसे निष्पादित किया जाता है और जब आप मॉक के साथ बातचीत करते हैं तो एक वापसी मान दिया जाता है।

@Test
public void test_answer() throws Exception {
    Dummy dummy = mock(Dummy.class);
    Answer<Integer> answer = new Answer<Integer>() {
        public Integer answer(InvocationOnMock invocation) throws Throwable {
            String string = invocation.getArgumentAt(0, String.class);
            return string.length() * 2;
        }
    };

    // choose your preferred way
    when(dummy.stringLength("dummy")).thenAnswer(answer);
    doAnswer(answer).when(dummy).stringLength("dummy");
}

हाय @ रोलैंड वील्डर लेकिन कभी-कभी आपको कुछ आंतरिक कोड उत्पन्न मूल्य वापस करने चाहिए और कुछ भी नहीं करना चाहिए, उदाहरण के लिए code = UUID.randomUUID(), मुझे इस के साथ लागू करना असंभव लगा mockito
जुगुओवेई

3
जब आपके मॉक को प्रत्येक आह्वान के लिए एक नया यूयूआईडी वापस करना चाहिए, जिसे आप Answerबस के साथ लागू करेंगे return UUID.randomUUID();
रोलैंड वीजेलडर

क्या मैं इस विधि को नए उत्तर से ले सकता हूं, आरंभीकरण चींटी ने इसे किसी विधि में डाल दिया, ताकि कोड को थोड़ा अधिक क्लीनर बनाया जा सके?
रेखा

3
@ लीन Answerएक कार्यात्मक इंटरफ़ेस है, इसलिए जावा 8 के साथ आप इसे लैम्ब्डा अभिव्यक्ति के साथ बदल सकते हैं। यदि किसी अन्य सामान्य रूप से पर्याप्त साफ नहीं है और असामान्य रीफैक्टरिंग संभव है।
रोलैंड वीजेलडर

@ zhuguowei: आंतरिक कोड उत्पन्न कुछ मूल्य लौटाएं? उससे तुम्हारा क्या मतलब है?
सौरभ पाटिल

34

doAnswerऔर thenReturnअगर वही काम करें:

  1. आप मॉक का उपयोग कर रहे हैं, स्पाई का नहीं
  2. जिस विधि से आप लड़खड़ा रहे हैं, वह मान लौट रहा है, शून्य विधि नहीं।

चलिए इस BookService का मजाक उड़ाते हैं

public interface BookService {
    String getAuthor();
    void queryBookTitle(BookServiceCallback callback);
}

आप getAuthor () का उपयोग कर ठूंठ कर सकते हैं doAnswerऔर thenReturn

BookService service = mock(BookService.class);
when(service.getAuthor()).thenReturn("Joshua");
// or..
doAnswer(new Answer() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        return "Joshua";
    }
}).when(service).getAuthor();

ध्यान दें कि उपयोग करते समय doAnswer, आप एक विधि पास नहीं कर सकते when

// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());

तो, आप doAnswerइसके बजाय कब उपयोग करेंगे thenReturn? मैं दो उपयोग मामलों के बारे में सोच सकता हूं:

  1. जब आप शून्य विधि "स्टब" करना चाहते हैं।

DoAnswer का उपयोग करके आप विधि मंगलाचरण पर कुछ अतिरिक्त क्रियाएँ कर सकते हैं। उदाहरण के लिए, queryBookTitle पर कॉलबैक ट्रिगर करें।

BookServiceCallback callback = new BookServiceCallback() {
    @Override
    public void onSuccess(String bookTitle) {
        assertEquals("Effective Java", bookTitle);
    }
};
doAnswer(new Answer() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        BookServiceCallback callback = (BookServiceCallback) invocation.getArguments()[0];
        callback.onSuccess("Effective Java");
        // return null because queryBookTitle is void
        return null;
    }
}).when(service).queryBookTitle(callback);
service.queryBookTitle(callback);
  1. जब आप मॉक की जगह स्पाई का इस्तेमाल कर रहे हों

स्पाई मॉकिटो पर जब-तब रीटर्न का उपयोग करते समय वास्तविक विधि को कॉल करेगा और फिर अपने उत्तर को स्टब करेगा। यदि आप वास्तविक विधि को कॉल नहीं करना चाहते हैं तो यह समस्या पैदा कर सकता है, जैसे कि इस नमूने में:

List list = new LinkedList();
List spy = spy(list);
// Will throw java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
when(spy.get(0)).thenReturn("java");
assertEquals("java", spy.get(0));

DoAnswer का उपयोग करके हम इसे सुरक्षित रूप से स्टब कर सकते हैं।

List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));

दरअसल, यदि आप विधि मंगलाचरण पर अतिरिक्त कार्य नहीं करना चाहते हैं, तो आप बस उपयोग कर सकते हैं doReturn

List list = new LinkedList();
List spy = spy(list);
doReturn("java").when(spy).get(0);
assertEquals("java", spy.get(0));

क्या होगा अगर नकली विधि शून्य है?
इगोर डोनिन

1
इगोर, यह बिल्कुल ऐसा है जहाँ doAnswer () चित्र में आता है और उसने ऊपर के उत्तर में इसे कवर किया है।
सौरभ पाटिल

उपयोग करते समय doAnswer(new Answer() { ... return null;}मुझे ग्रहण में चेतावनी मिलती है "उत्तर एक कच्चा प्रकार है। सामान्य प्रकार का संदर्भ उत्तर <टी> पैरामीटर होना चाहिए"। क्या इसका समाधान करने का कोई तरीका है (चेतावनी की अनदेखी को छोड़कर)?
लेज़र
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.