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?
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());
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")));
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());
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));
}
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:"));
}