एक ही तर्क के साथ एक ही विधि के लिए कई कॉल के साथ मॉकिटो का उपयोग करना


289

वहाँ एक तरीका है एक stubbed विधि बाद में आह्वान पर विभिन्न वस्तुओं को वापस करने के लिए है? मैं एक से nondeterminate प्रतिक्रियाओं का परीक्षण करने के लिए यह करना चाहते हैं ExecutorCompletionService। परीक्षण के तरीकों की परवाह किए बिना कि परिणाम की परवाह किए बिना, परिणाम स्थिर रहता है।

मैं जिस कोड का परीक्षण करना चाहता हूं, वह कुछ ऐसा दिखता है।

// Create an completion service so we can group these tasks together
ExecutorCompletionService<T> completionService =
        new ExecutorCompletionService<T>(service);

// Add all these tasks to the completion service
for (Callable<T> t : ts)
    completionService.submit(request);

// As an when each call finished, add it to the response set.
for (int i = 0; i < calls.size(); i ++) {
    try {
        T t = completionService.take().get();
        // do some stuff that I want to test
    } catch (...) { }        
}

जवाबों:


254

आप ऐसा कर सकते हैं thenAnswerविधि का उपयोग कर (जब के साथ जंजीर when):

when(someMock.someMethod()).thenAnswer(new Answer() {
    private int count = 0;

    public Object answer(InvocationOnMock invocation) {
        if (count++ == 1)
            return 1;

        return 2;
    }
});

या समकक्ष, स्थिर doAnswerविधि का उपयोग कर :

doAnswer(new Answer() {
    private int count = 0;

    public Object answer(InvocationOnMock invocation) {
        if (count++ == 1)
            return 1;

        return 2;
    }
}).when(someMock).someMethod();

635

कैसा रहेगा

when( method-call ).thenReturn( value1, value2, value3 );

आप जितने तर्क देते हैं, उतने ही तर्क आप तत्पश्चात के कोष्ठक में रख सकते हैं, बशर्ते वे सभी सही प्रकार के हों। पहला मान लौटाया जाएगा पहली बार विधि कहा जाता है, फिर दूसरा उत्तर, और इसी तरह। अन्य मानों का उपयोग किए जाने पर अंतिम मान बार-बार लौटाया जाएगा।


4
यह एक मॉक के साथ काम करेगा, लेकिन जासूस के साथ नहीं। यदि आपको मूल विधि को कॉल करने से रोकने की आवश्यकता है, तो आपको doAnswer (...) की आवश्यकता है। जब (someSpy) .someMethod (...)।
यूरी

6
@ यूरी - काफी नहीं। आप जिस मामले का उल्लेख करते हैं, उसमें आपको doAnswerलिखने या लिखने की आवश्यकता नहीं है Answer। आप बस इस्तेमाल कर सकते हैं doReturn(...).when(someSpy).someMethod(...)। यह मानना ​​उचित है कि एम्मा जासूसी के बजाय, मोक्स में रुचि रखती है, लेकिन मुझे लगता है कि मैं अपने उत्तर के लिए कुछ जोड़ सकता हूं। टिप्पणी के लिए धन्यवाद।
दाऊद इब्न करीम

@DawoodibnKareem पहली कॉल के लिए कहता है कि मैं एक मूल्य वापस करना चाहता हूं और दूसरी कॉल के लिए मैं एक अपवाद फेंकना चाहता हूं। यह कैसे किया जा सकता है?
रिटो सेप

@Rito कृपया वलोडिमिर का जवाब या रेस्टॉर्म का जवाब पढ़ें। वे दोनों उस मामले को कवर करते हैं।
दाऊद इब्न करीम

ऐसा शानदार जवाब।
Wild_nothing

151

जैसा कि पहले बताया गया है कि लगभग सभी कॉल चेनेबल हैं।

तो आप कॉल कर सकते थे

when(mock.method()).thenReturn(foo).thenReturn(bar).thenThrow(new Exception("test"));

//OR if you're mocking a void method and/or using spy instead of mock

doReturn(foo).doReturn(bar).doThrow(new Exception("Test").when(mock).method();

मॉकिटो के डोक्यूमिनेशन में अधिक जानकारी ।


3
बहुत मददगार! mock.methodइस उदाहरण में 4 वीं बार क्या कहा जाएगा ? मुझे कुछ पसंद है, पहली बार फू लौटाओ लेकिन बाकी सभी के लिए वापसी बार।
javaPlease42

6
मॉक पर प्रत्येक अतिरिक्त आह्वान अंतिम 'तत्पश्चात पुनर्नवा' या अंतिम 'तत्पश्चात' अति उपयोगी होगा
फ्रेंकोइस

महान और सरल निर्देशों के लिए धन्यवाद। अब तक यह कभी नहीं पता था। मैं यह जानने के लिए संघर्ष कर रहा था कि दो समान कॉल पर दो अलग-अलग परिणाम कैसे प्राप्त करें। मुझे टन बचाओ।
चार्ल्स सीपी


4

मैंने एक MultipleAnswerवर्ग लागू किया है जो मुझे हर कॉल में अलग-अलग उत्तर देने में मदद करता है। यहाँ कोड का टुकड़ा:

private final class MultipleAnswer<T> implements Answer<T> {

    private final ArrayList<Answer<T>> mAnswers;

    MultipleAnswer(Answer<T>... answer) {
        mAnswers = new ArrayList<>();
        mAnswers.addAll(Arrays.asList(answer));
    }

    @Override
    public T answer(InvocationOnMock invocation) throws Throwable {
        return mAnswers.remove(0).answer(invocation);
    }
}

1
क्या आप उस वस्तु को संक्षिप्त, सरल और पठनीय तरीके से आरंभ कर सकते हैं?
usr-local-

1

विभिन्न विधि कॉल पर विभिन्न तर्कों को वापस करने के लिए एक सामान्य विधि के रूप में निम्नलिखित का उपयोग किया जा सकता है। केवल एक चीज जो हमें करने की आवश्यकता है वह यह है कि हमें एक सरणी को क्रम से पास करने की आवश्यकता है जिसमें वस्तुओं को प्रत्येक कॉल में पुनर्प्राप्त किया जाना चाहिए।

@SafeVarargs
public static <Mock> Answer<Mock> getAnswerForSubsequentCalls(final Mock... mockArr) {
    return new Answer<Mock>() {
       private int count=0, size=mockArr.length;
       public Mock answer(InvocationOnMock invocation) throws throwable {
           Mock mock = null;
           for(; count<size && mock==null; count++){
                mock = mockArr[count];
           }

           return mock;    
       } 
    }
}

पूर्व। getAnswerForSubsequentCalls(mock1, mock3, mock2);पहली कॉल पर mock1 ऑब्जेक्ट लौटाएगा, दूसरी कॉल पर mock3 ऑब्जेक्ट और तीसरी कॉल पर mock2 ऑब्जेक्ट। when(something()).doAnswer(getAnswerForSubsequentCalls(mock1, mock3, mock2)); इस तरह इस्तेमाल किया जाना चाहिए यह लगभग समान हैwhen(something()).thenReturn(mock1, mock3, mock2);


1

8 साल पहले के @ [इगोर निकोलेव] के जवाब से संबंधित, जावा 8 में उपलब्ध लंबोदर अभिव्यक्तिAnswer का उपयोग करके कुछ हद तक सरलीकृत किया जा सकता है ।

when(someMock.someMethod()).thenAnswer(invocation -> {
    doStuff();
    return;
});

या अधिक बस:

when(someMock.someMethod()).thenAnswer(invocation -> doStuff());

1

BDD शैली:

import static org.mockito.BDDMockito.*;
...
    @Test
    void submit() {
        given(yourMock.yourMethod()).willReturn(1, 2, 3);

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.