Какой у вас опыт работы с моками (mock objects) в unit-тестировании?

«Какой у вас опыт работы с моками (mock objects) в unit-тестировании?» — вопрос из категории Тестирование, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Имею практический опыт использования мок-объектов для изоляции тестируемого класса, преимущественно с фреймворком Mockito.

Типичные сценарии применения:

  1. Создание моков: Аннотации @Mock и @InjectMocks или ручное создание через Mockito.mock().
  2. Задание поведения: Определение ответов мока на вызовы его методов.
    when(userRepository.findById(anyLong()))
        .thenReturn(Optional.of(new User("testUser")));
    when(notificationService.send(any()))
        .thenThrow(new RuntimeException("Service unavailable"));
  3. Верификация взаимодействий: Проверка, что тестируемый код корректно взаимодействует с зависимостями.
    verify(emailService, times(1)).sendWelcomeEmail(userCaptor.capture());
    verify(analyticsClient, never()).trackEvent(any());
  4. Захват аргументов: Использование ArgumentCaptor для проверки передаваемых объектов.

Ключевое понимание: Моки нужны для тестирования логики класса, а не его зависимостей. Избыточное мокирование или мокирование сложных внутренних вызовов — признак плохого дизайна класса (нарушение SRP). В таких случаях предпочитаю рефакторинг, а не использование PowerMock для обхода ограничений (например, мокирования static или final методов).