Какие объекты рекомендуется заменять моками в юнит тестах?
Что проверяют
Понимаете ли вы, зачем нужны моки: изолировать тестируемый класс от медленного, недетерминированного и внешнего. Следом обычно спрашивают обратное: что мокать не надо и чем мок отличается от стаба и фейка.
Как отвечать
Мокают границы, за которыми начинается то, что тест не контролирует:
- внешние системы: HTTP-клиенты, брокеры сообщений, почтовые и платёжные шлюзы. Запрос в сеть делает юнит-тест медленным и нестабильным;
- репозитории и DAO: в юнит-тесте сервиса слой данных подменяют, а работу с настоящей базой проверяют интеграционными тестами на Testcontainers;
- время и случайность: вместо
LocalDateTime.now()в класс внедряютjava.time.Clock, в тесте берутClock.fixed(). То же с генерацией UUID иRandom; - файловая система и окружение: чтение файлов и переменных среды прячут за своим интерфейсом.
Что не мокают: объекты значений, DTO, коллекции, сам тестируемый класс и простые классы без побочных эффектов, которые проще создать через new. И типы, которыми вы не владеете: внешнюю библиотеку лучше обернуть своим адаптером и мокать его.
Инструменты: Mockito с @ExtendWith(MockitoExtension.class), @Mock, @InjectMocks, when(...).thenReturn(...) и verify(...). С Mockito 5 по умолчанию включён inline mock maker, поэтому финальные классы и mockStatic() работают без дополнительной настройки. В Spring Boot с версии 3.4 @MockBean помечен устаревшим, вместо него @MockitoBean из Spring Framework 6.2. Для HTTP часто удобнее не мок клиента, а WireMock.
Различие терминов: стаб отдаёт заготовленный ответ, мок ещё и проверяет, как его вызвали, фейк это рабочая упрощённая реализация вроде репозитория на HashMap.
Где спотыкаются
Мокают всё подряд. Тест проверяет порядок вызовов и ломается от любого рефакторинга, хотя поведение не менялось.
Мокают репозиторий и на этом останавливаются. Ошибка в запросе или маппинге так и остаётся непойманной, потому что интеграционного теста нет.
Ставят verify() там, где достаточно проверить результат. Проверять вызов стоит только для побочных эффектов: отправили письмо, записали событие.