Можно ли с помощью 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());
// затем выполняю утверждения на secondFooCaptor.getValue()
Но я получаю исключение TooManyActualInvocations
, так как Mockito считает, что doSomething
должен быть вызван только один раз.
Как я могу проверить аргумент второго вызова метода doSomething
?
3 ответ(ов)
Вы также можете использовать аннотированный @Captor ArgumentCaptor. Например:
@Mock
List<String> mockedList;
@Captor
ArgumentCaptor<String> argCaptor;
@BeforeTest
public void init() {
// Инициализируем объекты, аннотированные @Mock, @Captor и @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));
}
В этом примере мы создаем мок-объект mockedList
и используем @Captor
для захвата аргументов, передаваемых в метод add
. В методе теста shouldCallAddMethodTwice
мы вызываем метод add
дважды, а затем проверяем, что он был вызван именно с теми значениями, которые мы ожидаем. Использование argCaptor
позволяет нам получить доступ к аргументам, переданным в мок-объект, что делает тестирование более удобным и наглядным.
С помощью лямбд в Java 8 удобно использовать следующий подход с Mockito:
import static org.mockito.Mockito.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
when(client.deleteByQuery(anyString(), anyString())).then(invocationOnMock -> {
assertEquals("myCollection", invocationOnMock.getArgument(0));
assertThat(invocationOnMock.getArgument(1), startsWith("id:"));
});
В этом примере мы используем метод when
, чтобы задать поведение мок-объекта client
. Мы передаем лямбд и используем invocationOnMock
, чтобы получить аргументы, переданные в метод deleteByQuery
. Затем мы проверяем, что первый аргумент равен "myCollection"
, а второй аргумент начинается с "id:"
. Этот подход позволяет гибко реагировать на вызовы методов с помощью моков и производить необходимые проверки аргументов.
Во-первых, вам всегда следует импортировать статические методы Mockito, так код будет гораздо более читаемым (и интуитивно понятным) — примеры кода ниже требуют этого для работы:
import static org.mockito.Mockito.*;
В методе verify()
вы можете передать 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());
}
Список всех переданных аргументов во время вашего теста доступен через метод argument.getAllValues()
.
Значение единственного (последнего вызванного) аргумента можно получить с помощью argument.getValue()
, чтобы использовать его для дальнейшей обработки, проверки или любых других нужд.
Как замокировать методы с возвращаемым типом void с помощью Mockito
Как проверить, что конкретный метод не был вызван, используя Mockito?
Mockito: Тестирование void метода, который выбрасывает исключение
Использование Mockito для мокирования некоторых методов, но не всех
Запуск одного тестового метода с помощью Maven