Как протестировать void метод с помощью Mockito
Что проверяют
Понимаете ли вы, что у void-метода нет результата для сравнения и проверять приходится побочный эффект: вызовы зависимостей, изменение состояния или исключение. Следом спрашивают, как заставить void-метод мока бросить исключение.
Как отвечать
Сначала определите, что делает метод, от этого зависит способ проверки:
- вызывает зависимость:
verify(repository).save(expected). Количество уточняется вторым аргументом:times(2),never(),atLeastOnce(), порядок вызовов проверяетInOrder; - передаёт сложный объект:
ArgumentCaptor<Order>, затемverify(repository).save(captor.capture())и проверка полей черезcaptor.getValue(). Это честнее, чемany(), который пропустит что угодно; - меняет состояние: проверяйте результат через публичные методы объекта, мок тут не нужен;
- бросает исключение:
assertThrows(IllegalArgumentException.class, () -> service.saveData(null))из JUnit Jupiter.
Поведение void-методов мока задаётся через семейство do..., потому что when(mock.voidMethod()) не компилируется: void нельзя передать аргументом.
doThrow(IllegalStateException.class).when(sender).send(any()): имитирует падение зависимости, чтобы проверить обработку ошибки. Проверяемое исключение Mockito примет, только если метод объявляет его вthrows;doAnswer(inv -> ...): когда void-метод должен вызвать колбэк или изменить переданный объект;doNothing(): у обычного мока это и так поведение по умолчанию, пригождается дляspy, чтобы не выполнять реальный метод.
Каркас теста: @ExtendWith(MockitoExtension.class), поля с @Mock и @InjectMocks. Расширение работает в строгом режиме и падает с UnnecessaryStubbingException на неиспользованных заглушках.
Где спотыкаются
Пишут when(...).thenThrow(...) для void-метода и не понимают ошибку компиляции.
Смешивают матчеры и значения: verify(repo).save(eq("a"), 5) падает с InvalidUseOfMatchersException. Если есть хоть один матчер, матчерами должны быть все аргументы.
Верифицируют каждый вызов подряд, включая геттеры. Тест фиксирует реализацию, а не поведение, и ломается при любом рефакторинге.