Gymterview
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 не скомпилируется.