Может ли Mockito захватывать аргументы метода, называемого несколько раз?
У меня есть метод, который вызывается дважды, и я хочу захватить аргумент второго вызова метода.
Вот что я пробовал:
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
, поскольку Mockito считает, что doSomething
следует вызывать только один раз.
Как проверить аргумент второго вызова doSomething
?
Ответы
Ответ 1
Я думаю, что это должно быть
verify(mockBar, times(2)).doSomething(...)
Образец из 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());
Ответ 2
Если вы не хотите проверять все вызовы на doSomething()
, только последний, вы можете просто использовать ArgumentCaptor.getValue()
. Согласно Mockito javadoc:
Если метод вызывается несколько раз, он возвращает последнее зафиксированное значение
Итак, это сработает (предполагается, что 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());
Ответ 3
Так как Mockito 2.0 также имеет возможность использовать статический метод Matchers.argThat(ArgumentMatcher). С помощью Java 8 теперь стало намного чище и читаемо писать:
verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("OneSurname")));
verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("AnotherSurname")));
Если вы привязаны к более низкой версии Java, там также не так-плохо:
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")));