В чем разница между Mock и Spy в Mockito?

«В чем разница между Mock и Spy в Mockito?» — вопрос из категории Тестирование, который задают на 23% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Mock создает полностью заглушенный объект-пустышку. Все его методы по умолчанию возвращают "пустые" значения (null, 0, false), если их поведение не задано явно через when(...).thenReturn(...).

Spy (шпион) оборачивает реальный объект. Он вызывает настоящие методы исходного объекта, если они не были переопределены (замоканы) явно.

Ключевое отличие: Mock начинает с "чистого листа", а Spy — с поведения реального объекта.

Пример:

// 1. Mock
List<String> mockList = Mockito.mock(List.class);
mockList.add("test"); // Ничего не происходит, метод заглушен
System.out.println(mockList.size()); // 0 (значение по умолчанию для int)
System.out.println(mockList.get(0)); // null (значение по умолчанию для Object)

// 2. Spy
List<String> realList = new ArrayList<>();
List<String> spyList = Mockito.spy(realList); // Оборачиваем реальный список

spyList.add("real element"); // Реальное добавление в список!
System.out.println(spyList.size()); // 1 (вызван реальный метод)

// Мокируем конкретный метод у Spy
Mockito.when(spyList.size()).thenReturn(100);
System.out.println(spyList.size()); // 100 (возвращает мок-значение)
// Но список по-прежнему содержит 1 реальный элемент

Когда использовать:

  • Mock: Для полной изоляции тестируемого класса, когда все зависимости должны быть контролируемыми заглушками.
  • Spy: Для частичного мокирования, когда нужно заменить поведение только некоторых методов тяжелого или сложного объекта, сохранив остальную реальную логику.