क्या मॉकिटो कई बार नामक विधि के तर्कों को पकड़ सकता है?


446

मेरे पास एक विधि है जिसे दो बार कहा जाता है, और मैं दूसरी विधि कॉल के तर्क को पकड़ना चाहता हूं।

यहाँ मैंने कोशिश की है:

ArgumentCaptor<Foo> firstFooCaptor = ArgumentCaptor.forClass(Foo.class);
ArgumentCaptor<Foo> secondFooCaptor = ArgumentCaptor.forClass(Foo.class);
verify(mockBar).doSomething(firstFooCaptor.capture());
verify(mockBar).doSomething(secondFooCaptor.capture());
// then do some assertions on secondFooCaptor.getValue()

लेकिन मुझे एक TooManyActualInvocationsअपवाद मिलता है , जैसा कि मॉकिटो को लगता है कि doSomethingकेवल एक बार बुलाया जाना चाहिए।

मैं दूसरी कॉल के तर्क को कैसे सत्यापित कर सकता हूं doSomething?

जवाबों:


784

मुझे लगता है कि यह होना चाहिए

verify(mockBar, times(2)).doSomething(...)

मॉकिटो जावदोक से नमूना :

ArgumentCaptor<Person> peopleCaptor = ArgumentCaptor.forClass(Person.class);
verify(mock, times(2)).doSomething(peopleCaptor.capture());

List<Person> capturedPeople = peopleCaptor.getAllValues();
assertEquals("John", capturedPeople.get(0).getName());
assertEquals("Jane", capturedPeople.get(1).getName());

3
क्या आप इसके doSomething()साथ प्रत्येक अलग आह्वान में पारित तर्कों को पकड़ सकते हैं ?
मैट बी

36
यह ध्यान दिया जाना चाहिए कि यदि आप ऐसा कुछ करते हैं: Person person = new Person("John"); doSomething(person); person.setName("Jane"); doSomething(person);कैप्चर किया गया तर्क दो बार एक ही होगा (क्योंकि वास्तव में यह एक ही व्यक्ति ऑब्जेक्ट है), इसलिए capturedPeople.get(0).getName() == capturedPeople.get(1).getName() == "Jane", समूहों को भी देखें। UIforum/# ​​-msg/mockito/ KBRocVedYT0 / 5HtARMl9r2wJ
अस्माइर

2
यह अच्छा है, लेकिन मैं दो अलग-अलग टाइप किए गए ऑब्जेक्ट इनवोकेशन का परीक्षण कैसे कर सकता हूं? उदाहरण के लिए ExecutorService.submit (new MyRunableImpl ()); और फिर ExecutorService.submit (नया MyAnotherRunableImpl ())?
लियोन

अगर किसी को @asmaier द्वारा वर्णित मामले को संभालने की आवश्यकता है, तो मैंने यहां एक उत्तर पोस्ट किया: stackoverflow.com/a/36574817/1466267
स्पेसटुकर

1
लियोन के प्रश्न के उत्तर के बारे में सोच रहे किसी के लिए भी, आप सामान्य बेस क्लास ( Runnable) का उपयोग करेंगे और यदि आवश्यक हो, तो कैप्चर किए गए तर्क पर अधिक विशिष्ट प्रकार की जांच करें।
मैथ्यू पढ़ें

50

मॉकिटो 2.0 के बाद से स्थिर विधि Matchers.argThat (ArgumentMatcher) का उपयोग करने की संभावना है । जावा 8 की मदद से अब यह बहुत साफ है और लिखने के लिए अधिक पठनीय है:

verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("OneSurname")));
verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("AnotherSurname")));

यदि आप निचले जावा संस्करण से बंधे हैं, तो वह भी खराब नहीं है:

verify(mockBar).doSth(argThat(new ArgumentMatcher<Employee>() {
        @Override
        public boolean matches(Object emp) {
            return ((Employee) emp).getSurname().equals("SomeSurname");
        }
    }));

बेशक उनमें से कोई भी कॉल के आदेश को सत्यापित नहीं कर सकता है - जिसके लिए आपको InOrder का उपयोग करना चाहिए :

InOrder inOrder = inOrder(mockBar);

inOrder.verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("FirstSurname")));
inOrder.verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("SecondSurname")));

कृपया mockito-java8 प्रोजेक्ट पर एक नज़र डालें, जो कॉल करना संभव बनाता है जैसे:

verify(mockBar).doSth(assertArg(arg -> assertThat(arg.getSurname()).isEqualTo("Surname")));

2
यह एक अच्छी तकनीक है। मैं वर्तमान में कुछ क्रिप्टो आउटपुट प्राप्त कर रहा हूं, हालांकि: "वांटेड, लेकिन इनवॉइस नहीं: / n mockAppender.append (<इंडेक्स मैनेजर $ $ लाम्बा $ 5 9/1 3 1 9 5 1 0 1 1 6>);" - वहाँ arg एक है CharSequence। क्या आप "वांटेड" arg को ठीक से प्रिंट करने के लिए रिपोर्ट प्राप्त करने का कोई तरीका जानते हैं?
माईक कृंतक

यदि आप एक वर्ग बनाने के अधिक क्रिया मार्ग पर जाते हैं जो ArgumentMatcher <T> को लागू करता है, तो @mikerodent क्रिप्टिक आउटपुट तय किया जा सकता है। आपके कार्यान्वयन में स्ट्रोस्टिंग विधि को ओवरराइड करने से मॉकिटो टेस्ट आउटपुट में इच्छित कोई भी संदेश मिलेगा।
नूह सोलोमन

25

यदि आप सभी कॉलों को doSomething()केवल पिछले एक को मान्य नहीं करना चाहते हैं , तो आप इसका उपयोग कर सकते हैं ArgumentCaptor.getValue()मॉकिटो जावदोक के अनुसार :

यदि विधि को कई बार बुलाया गया था तो यह नवीनतम कैप्चर किए गए मान को लौटाता है

तो यह काम करेगा ( Fooमाना जाता है कि एक विधि है getName()):

ArgumentCaptor<Foo> fooCaptor = ArgumentCaptor.forClass(Foo.class);
verify(mockBar, times(2)).doSomething(fooCaptor.capture());
//getValue() contains value set in second call to doSomething()
assertEquals("2nd one", fooCaptor.getValue().getName());

क्या दोनों मूल्यों को पकड़ने का कोई तरीका है?
Hars

9

आप @Captor एनोटेट ArgumentCaptor का भी उपयोग कर सकते हैं। उदाहरण के लिए:

@Mock
List<String> mockedList;

@Captor
ArgumentCaptor<String> argCaptor;

@BeforeTest
public void init() {
    //Initialize objects annotated with @Mock, @Captor and @Spy.
    MockitoAnnotations.initMocks(this);
}

@Test
public void shouldCallAddMethodTwice() {
    mockedList.add("one");
    mockedList.add("two");
    Mockito.verify(mockedList, times(2)).add(argCaptor.capture());

    assertEquals("one", argCaptor.getAllValues().get(0));
    assertEquals("two", argCaptor.getAllValues().get(1));
}

6

जावा 8 के लैम्ब्डा के साथ, एक सुविधाजनक तरीका उपयोग करना है

org.mockito.invocation.InvocationOnMock

when(client.deleteByQuery(anyString(), anyString())).then(invocationOnMock -> {
    assertEquals("myCollection", invocationOnMock.getArgument(0));
    assertThat(invocationOnMock.getArgument(1), Matchers.startsWith("id:"));
}

मैं यह देखने में सक्षम नहीं हूं कि यह पुराने तरीके से कैसे अधिक सुविधाजनक है। मुझे लंबोदर का अच्छा उपयोग पसंद है, लेकिन मुझे यकीन नहीं है कि यह एक है।
एरिक विल्सन

0

सबसे पहले: आपको हमेशा मॉकिटो स्थैतिक आयात करना चाहिए, इस तरह से कोड बहुत अधिक पठनीय (और सहज) होगा - नीचे दिए गए कोड नमूने इसे काम करने की आवश्यकता है:

import static org.mockito.Mockito.*;

सत्यापन () विधि में आप तर्क में परीक्षण का मूल्यांकन करने के लिए ArgumentCaptor और तर्क का मूल्यांकन करने के लिए ArgumentCaptor पास कर सकते हैं:

ArgumentCaptor<MyExampleClass> argument = ArgumentCaptor.forClass(MyExampleClass.class);
verify(yourmock, atleast(2)).myMethod(argument.capture());

List<MyExampleClass> passedArguments = argument.getAllValues();

for (MyExampleClass data : passedArguments){
    //assertSometing ...
    System.out.println(data.getFoo());
}

आपके परीक्षण के दौरान सभी पास किए गए तर्कों की सूची तर्क.getAllValues ​​() विधि के माध्यम से सुलभ है।

एकल (अंतिम कहा जाता है) तर्क का मान तर्क के माध्यम से सुलभ है। आगे के हेरफेर / जाँच या आप जो भी करना चाहते हैं उसके लिए।

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