Mockito — что это, ключевые понятия и принцип работы

Автор: IT Sectr Опубликовано: 2026-04-08 Время чтения: 8 мин

Mockito — это фреймворк с открытым исходным кодом для создания mock-объектов в модульных тестах Java и Kotlin, который позволяет изолировать тестируемый код от внешних зависимостей. С его помощью разработчик подменяет реальные репозитории, API-клиенты и базы данных контролируемыми заглушками с заданным поведением. По данным Mockito.org, библиотека используется более чем в 60% Java-проектов, применяющих модульное тестирование.

Главное

  • Mockito — библиотека для создания mock-объектов, заменяющих реальные зависимости в тестах.
  • Mock — объект-заглушка, который имитирует поведение реального компонента.
  • Stubbing — настройка возвращаемого значения при вызове метода мока.
  • Verify — проверка того, что метод был вызван с определёнными аргументами.
  • @InjectMocks — автоматическое внедрение mock-зависимостей в тестируемый объект.

Что такое Mockito?

Mockito — это библиотека с открытым исходным кодом для создания mock-объектов (заглушек) в модульных тестах на Java, Kotlin и других языках JVM. В отличие от JUnit, который отвечает за запуск тестов, Mockito решает проблему изоляции — подменяет реальные зависимости тестируемого класса предсказуемыми объектами.

Без моков тестирование метода, который обращается к базе данных или внешнему API, требует настройки реального окружения — развёртывания БД, запуска сервера. Mockito заменяет эти зависимости объектами с фиксированным поведением: метод repository.findById(1) всегда возвращает заданный объект User, не обращаясь к базе.

Архитектура Mockito основана на паттерне Proxy (для интерфейсов и классов). Библиотека генерирует подкласс или прокси для указанного типа и перехватывает все вызовы методов, возвращая значения по умолчанию или заданные через when().thenReturn().

Как работает Mockito

Принцип работы Mockito строится на трёх базовых операциях: создание мока, настройка поведения (stubbing) и проверка вызовов (verification). Каждая операция использует статические методы из класса org.mockito.Mockito — самого загружаемого класса в экосистеме Java по статистике Maven Central. Все вызовы методов мока записываются в память, что позволяет позже проверить их через verify.

Три шага теста с Mockito

Типичный тест с Mockito состоит из трёх фаз: Arrange — создание моков и настройка стабов через when().thenReturn(), Act — вызов тестируемого метода, Assert — проверка результата через assertEquals и verify(мок). Такой подход называется AAA (Arrange-Act-Assert).

Базовый пример с моком репозитория

Рассмотрим простейший тест, где Mockito подменяет репозиторий пользователей. Метод when().thenReturn() настраивает мок так, чтобы вызов findById возвращал заранее подготовленный объект User.

java
// Создаём мок репозитория
UserRepository mockRepo = mock(UserRepository.class);

// Настраиваем поведение: при findById(1) вернуть пользователя
when(mockRepo.findById(1)).thenReturn(new User("Alice"));

// Проверяем, что метод действительно был вызван
User result = mockRepo.findById(1);
assertEquals("Alice", result.getName());
verify(mockRepo).findById(1);

Создание mock-объектов

Mockito предоставляет два способа создания моков: статический метод mock(Class) и аннотацию @Mock с инициализацией через MockitoAnnotations.openMocks(). Первый способ компактен для одного-двух моков, второй удобен, когда зависимостей много — аннотации сокращают boilerplate-код.

Через статический метод mock()

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

java
ApiClient apiClient = mock(ApiClient.class);
Database database = mock(Database.class);

Через аннотацию @Mock с JUnit 5

Аннотация @Mock в сочетании с @ExtendWith(MockitoExtension.class) автоматически создаёт моки для всех полей тестового класса. Расширение MockitoExtension отвечает за инициализацию перед каждым тестом.

java
@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void getUserShouldReturnUserFromRepo() {
        when(userRepository.findById(1)).thenReturn(new User("Alice"));
        User result = userService.getUser(1);
        assertEquals("Alice", result.getName());
    }
}

Stubbing: настройка поведения мока

Stubbing — это процесс определения того, что должен вернуть метод мока при вызове с определёнными аргументами. Базовый синтаксис: when(mock.method(args)).thenReturn(value). Для разных сценариев Mockito предлагает несколько вариантов then-методов.

МетодНазначение
thenReturn(value)Всегда возвращает указанное значение
thenThrow(exception)Выбрасывает исключение при вызове
thenAnswer(answer)Вычисляет возвращаемое значение динамически
thenCallRealMethod()Вызывает реальный метод (частичный мок)

Динамический ответ через thenAnswer

Когда возвращаемое значение зависит от аргументов вызова, используется thenAnswer с лямбдой. Это полезно для имитации работы с реальными данными — например, генерации ID на основе переданного объекта.

java
when(repository.save(any())).thenAnswer(invocation -> {
    User user = invocation.getArgument(0);
    user.setId(42);
    return user;
});

Verify: проверка взаимодействий с моком

Verify — это уникальная возможность Mockito, которую не предоставляют более старые библиотеки mock-объектов (EasyMock, jMock).

Verify делает тесты более надёжными, так как проверяет не только возвращаемое значение, но и побочные эффекты — вызовы методов, которые не возвращают результат (void-методы). Метод verify(mock).methodName(args) проверяет, был ли вызван определённый метод мока с указанными аргументами. Это позволяет тестировать не только результат, но и процесс — факт обращения к зависимости.

Проверка количества вызовов

По умолчанию verify проверяет, что метод был вызван ровно один раз. Если нужно другое количество — используется times(n), atLeast(n), never() и другие модификаторы из класса Mockito.

java
// Проверка количества вызовов
verify(repository, times(3)).save(any());
verify(repository, never()).delete(any());
verify(repository, atLeastOnce()).findById(1);

// Проверка порядка вызовов
InOrder inOrder = inOrder(repository);
inOrder.verify(repository).save(any());
inOrder.verify(repository).flush();

ArgumentCaptor для захвата аргументов

Когда нужно проверить, с каким именно объектом был вызван метод, используется ArgumentCaptor. Он захватывает значение аргумента во время вызова и позволяет проверить его поля по отдельности. ArgumentCaptor особенно полезен, когда тестируемый код создаёт объект внутри себя и передаёт его в зависимость — вы не можете проверить этот объект иначе.

java
ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(repository).save(captor.capture());
assertEquals("Alice", captor.getValue().getName());

Аннотации @Mock и @InjectMocks

@Mock и @InjectMocks — две ключевые аннотации Mockito, которые значительно сокращают boilerplate-код. @Mock создаёт мок для поля, а @InjectMocks внедряет все моки из тестового класса в тестируемый объект через конструктор, сеттер или поле.

Механизм @InjectMocks пытается внедрить зависимости в следующем порядке: конструктор с наибольшим количеством аргументов, сеттер по типу, приватное поле. Если ни один способ не сработал — объект остаётся с null-зависимостями, и тест упадёт с NullPointerException.

Правила использования @InjectMocks

Важно понимать: @InjectMocks не анализирует типы полей — он подставляет любой мок, совместимый по типу. Если в классе два поля одного типа — Mockito может внедрить неправильный мок. В таких случаях рекомендуется использовать явный конструктор с передачей моков.

Mockito в Android-проектах

В Android-разработке Mockito применяется вместе с JUnit для тестирования ViewModel, Repository и UseCase. Поскольку эти классы выполняются на JVM без Android-контекста, Mockito подменяет их зависимости — Room DAO, Retrofit API, SharedPreferences — на стабы с предсказуемым поведением.

Настройка Gradle для Mockito

Для подключения Mockito в Android-проект достаточно добавить зависимость mockito-core или mockito-inline (последняя поддерживает мокирование final-классов и статических методов). Версия 5.12.0 (2024) включает поддержку Java 21 и улучшенную интеграцию с JUnit 5.

kotlin
// build.gradle.kts (module)
dependencies {
    testImplementation("org.mockito:mockito-core:5.12.0")
    testImplementation("org.mockito:mockito-junit-jupiter:5.12.0")
}

Mockito и PowerMock: устаревшая практика

Ранее для мокирования статических методов и конструкторов требовался PowerMock — расширение, работавшее через байткод-инструментацию. Начиная с Mockito 5.x с mockito-inline, эта возможность встроена напрямую: mockStatic(ClassName.class) позволяет мокировать статические методы без дополнительных библиотек.

Тестирование ViewModel с Mockito

Типичный сценарий: ViewModel вызывает метод репозитория и трансформирует результат в UI-состояние. Mockito подменяет репозиторий, а тест проверяет, что ViewModel корректно обрабатывает успешный ответ и ошибку. При использовании архитектуры Clean Architecture моки создаются для каждого слоя: DataSource, Repository и UseCase — это позволяет тестировать каждый слой изолированно.

  • success case — when(repo.getData()).thenReturn(Result.success(data)) → проверяем state = Success(data).
  • error case — when(repo.getData()).thenReturn(Result.error(exception)) → проверяем state = Error(message).
  • loading state — verify, что ViewModel установила isLoading = true перед вызовом репозитория.

Часто задаваемые вопросы

Чем Mockito отличается от MockK?

Mockito — библиотека для Java и Kotlin, использующая прокси и рефлексию. MockK — Kotlin-first библиотека с поддержкой корутин, extension-функций и final-классов без дополнительной конфигурации.

Как создать мок для final-класса в Mockito?

Начиная с Mockito 2.1, мокирование final-классов поддерживается через opt-in. В версии 5.x (mockito-inline) это включено по умолчанию. Достаточно добавить зависимость mockito-inline и использовать стандартный mock() метод.

Что такое Spy в Mockito?

Spy — это частичный мок, который по умолчанию вызывает реальные методы, но позволяет переопределить некоторые из них через when().thenReturn(). Spy полезен для тестирования legacy-кода, когда нельзя переписать весь класс.

В чём разница between thenReturn и thenAnswer?

thenReturn всегда возвращает одно и то же значение, независимо от аргументов. thenAnswer вычисляет возвращаемое значение на основе invocation — аргументов вызова, самого мока, состояния. Для динамических ответов всегда используйте thenAnswer.

Почему verify важен для тестов с моками?

Verify проверяет не только результат, но и процесс — факт обращения к зависимости. Это критично для сервисов, которые должны сохранять данные или отправлять уведомления. Без verify тест не обнаружит, что метод не вызвал save() или send().

Итоги

  • Mockito — библиотека для создания mock-объектов, стандарт de facto для мокирования в Java и Kotlin.
  • Моки создаются через mock(Class) или аннотацию @Mock с MockitoExtension.
  • Stubbing через when().thenReturn() задаёт поведение методов мока.
  • Verify проверяет факт и количество вызовов методов мока с указанными аргументами.
  • @InjectMocks автоматически внедряет моки в тестируемый объект.
  • Android-интеграция — Mockito используется для тестирования ViewModel, Repository и UseCase.
  • ArgumentCaptor захватывает аргументы вызова для детальной проверки полей объекта.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также