Как используется Mockito для модульного тестирования и каковы его основные возможности?

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

Ответ

Mockito — это ведущий фреймворк для создания мок-объектов (test doubles) в модульных тестах Java. Он позволяет изолировать тестируемый класс, подменяя его зависимости контролируемыми заглушками.

Основные возможности и использование:

  1. Создание моков и стабов:

    // Создание мока
    UserRepository mockRepo = Mockito.mock(UserRepository.class);
    
    // Задание поведения (stubbing)
    Mockito.when(mockRepo.findById(1L))
           .thenReturn(new User(1L, "Alice"));
    
    // Задание поведения для исключения
    Mockito.when(mockRepo.findById(999L))
           .thenThrow(new EntityNotFoundException());
    
    // Задание поведения для void-метода
    Mockito.doNothing().when(mockRepo).delete(Mockito.any());
  2. Проверка взаимодействий (verification):

    // Проверка, что метод был вызван ровно 1 раз с конкретным аргументом
    Mockito.verify(mockRepo).findById(1L);
    
    // Проверка количества вызовов
    Mockito.verify(mockRepo, Mockito.times(2)).save(Mockito.any(User.class));
    Mockito.verify(mockRepo, Mockito.never()).deleteAll();
  3. Использование аннотаций (с JUnit 5):

    @ExtendWith(MockitoExtension.class)
    class UserServiceTest {
    
        @Mock
        private UserRepository userRepository; // Зависимость для мокирования
    
        @InjectMocks
        private UserService userService; // Тестируемый сервис, куда внедряются моки
    
        @Test
        void getUserById_ShouldReturnUser() {
            Mockito.when(userRepository.findById(1L)).thenReturn(new User(1L, "Alice"));
            User result = userService.getUserById(1L);
            assertEquals("Alice", result.getName());
        }
    }

Ключевые преимущества Mockito:

  • Чистый и читаемый API: Позволяет писать понятные тесты.
  • Гибкость: Поддержка аргумент-матчеров (Mockito.eq(), Mockito.any(), Mockito.argThat()).
  • Интеграция: Отлично работает с JUnit 4/5 и Spring Test.
  • Детализация ошибок: Понятные сообщения при падении проверок (verification).

Важное замечание: Mockito используется для изоляции. Для тестирования взаимодействия с реальными базами данных или внешними сервисами следует применять интеграционные тесты с тестовыми контейнерами или in-memory базами.