it-swarm.com.de

Kann Mockito Argumente einer mehrfach aufgerufenen Methode erfassen?

Ich habe eine Methode, die zweimal aufgerufen wird, und ich möchte das Argument des zweiten Methodenaufrufs erfassen.

Folgendes habe ich versucht:

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()

Aber ich bekomme eine TooManyActualInvocations Ausnahme, da Mockito der Meinung ist, dass doSomething nur einmal aufgerufen werden sollte.

Wie kann ich das Argument des zweiten Aufrufs von doSomething überprüfen?

389
Eric Wilson

Ich denke es sollte sein

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

Probe aus mockito javadoc :

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());
697
proactif

Seit Mockito 2.0 gibt es auch die Möglichkeit, die statische Methode Matchers.argThat (ArgumentMatcher) zu verwenden. Mit Hilfe von Java 8 ist es jetzt viel übersichtlicher und lesbarer zu schreiben:

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

Wenn Sie an eine niedrigere Java -Version gebunden sind, ist dies auch nicht schlecht:

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

Natürlich kann keiner von diesen die Reihenfolge der Anrufe überprüfen - für die Sie InOrder verwenden sollten:

InOrder inOrder = inOrder(mockBar);

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

Bitte schauen Sie sich das mockito-Java8 Projekt an, das es ermöglicht, Anrufe zu tätigen wie:

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

Wenn Sie nicht alle Aufrufe von doSomething() validieren möchten, sondern nur den letzten, können Sie einfach ArgumentCaptor.getValue() verwenden. Nach dem Mockito javadoc :

Wenn die Methode mehrmals aufgerufen wurde, wird der zuletzt erfasste Wert zurückgegeben

Das würde also funktionieren (angenommen, Foo hat eine Methode 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());
25
lreeder

Sie können auch @Captor annotated ArgumentCaptor verwenden. Zum Beispiel:

@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));
}
8

Mit den Lambdas von Java 8 ist die Verwendung ein bequemer Weg

org.mockito.invocation.InvocationOnMock

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