middle
В чём разница между doReturn/when и when/thenReturn в Mockito?
Обе конструкции задают поведение мока, но имеют критические различия при работе со spy-объектами и void-методами.
when/thenReturn — стандартный подход
Вызывает реальный метод при настройке мока (что может вызвать проблемы для spy-объектов):
Пример
when(mock.someMethod()).thenReturn("результат");
doReturn/when — безопасный подход
Не вызывает реальный метод при настройке:
Пример
doReturn("результат").when(mock).someMethod();
Ключевые различия
1. Spy-объекты:
Пример
List<String> spyList = spy(new ArrayList<>());
// Опасно! get(0) вызовется на пустом списке → IndexOutOfBoundsException
// when(spyList.get(0)).thenReturn("элемент");
// Безопасно — реальный метод не вызывается при настройке
doReturn("элемент").when(spyList).get(0);
2. Void-методы:
Пример
// Не скомпилируется:
// when(mock.voidMethod()).thenThrow(new RuntimeException());
// Правильно:
doThrow(new RuntimeException("ошибка")).when(mock).voidMethod();
doNothing().when(mock).voidMethod();
3. Цепочка вызовов:
Пример
when(mock.nextValue())
.thenReturn("первый")
.thenReturn("второй")
.thenThrow(new NoSuchElementException());
Сводная таблица
| Метод | Когда использовать |
|---|---|
when/thenReturn |
Стандартный случай с моками |
doReturn/when |
Spy-объекты, void-методы |
doThrow/when |
Void-методы, которые должны бросить исключение |
doAnswer/when |
Сложная логика, зависящая от аргументов |
doNothing/when |
Подавление void-метода у spy |
На собеседовании: ключевой момент — объяснить, почему
when/thenReturnопасен для spy (реальный метод вызывается при настройке). Частая ошибка — не знать, что для void-методовwhen/thenReturnне скомпилируется.