Mockito для Java: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое Mockito и зачем он нужен?

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

Основная цель Mockito — сделать юнит-тесты быстрыми, предсказуемыми и независимыми от внешней среды. Библиотека широко используется в экосистеме Java (Spring, Java EE, Android) и является стандартом де-факто для мокирования.

Ключевые возможности:

  • Создание mock-объектов — имитация любого класса или интерфейса.
  • Определение поведения — настройка возвращаемых значений, выброс исключений.
  • Верификация вызовов — проверка, что методы вызывались с определенными параметрами и нужное количество раз.
  • Spy (частичное мокирование) — возможность использовать реальный объект, но переопределять отдельные методы.
  • Захват аргументов (ArgumentCaptor) — извлечение параметров, переданных в mock-метод, для дальнейшей проверки.

Установка Mockito

Поскольку Mockito — это Java-библиотека, она не устанавливается через pip или npm. Для подключения к проекту используются системы сборки Maven или Gradle.

Maven (pom.xml)

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.12.0</version>
    <scope>test</scope>
</dependency>

<!-- Для использования с JUnit 5 -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>5.12.0</version>
    <scope>test</scope>
</dependency>

Gradle (build.gradle)

testImplementation 'org.mockito:mockito-core:5.12.0'
testImplementation 'org.mockito:mockito-junit-jupiter:5.12.0'

Рекомендуется использовать последнюю стабильную версию, актуальную на момент написания тестов.

Быстрый старт: пример кода

Рассмотрим простой пример. Допустим, у нас есть класс UserService, который зависит от UserRepository. Мы хотим протестировать UserService, не поднимая базу данных.

// Класс репозитория (зависимость)
public interface UserRepository {
    User findById(Long id);
    void save(User user);
}

// Класс сервиса (тестируемый)
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public String getUserName(Long id) {
        User user = userRepository.findById(id);
        return user != null ? user.getName() : "Unknown";
    }
}

// Тест с использованием Mockito
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @Test
    public void testGetUserName() {
        // Создаем mock-объект UserRepository (можно через аннотацию @Mock)
        // UserRepository mockRepo = mock(UserRepository.class);

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

        // Создаем сервис с mock-репозиторием
        UserService userService = new UserService(userRepository);

        // Вызываем тестируемый метод
        String userName = userService.getUserName(1L);

        // Проверяем результат
        assertEquals("Alice", userName);

        // Верифицируем, что метод findById был вызван ровно один раз
        verify(userRepository, times(1)).findById(1L);
    }
}

Основные методы и функции Mockito

Ниже приведены 10 ключевых методов библиотеки с подробным описанием и примерами.

1. mock() — создание mock-объекта

Что делает: Создает имитацию класса или интерфейса. Все методы по умолчанию возвращают значения по умолчанию (null, 0, false) или пустые коллекции.

Параметры:

  • Class<T> classToMock — класс или интерфейс для мокирования.
  • String name (опционально) — имя mock-объекта для отладки.
  • Answer defaultAnswer (опционально) — стратегия ответа по умолчанию.

Пример:

List<String> mockedList = mock(List.class);
mockedList.add("one");
System.out.println(mockedList.size()); // Выведет 0, так как поведение не настроено

2. when().thenReturn() — настройка возвращаемого значения

Что делает: Определяет, какое значение должен вернуть метод mock-объекта при вызове с определенными аргументами.

Параметры:

  • methodCall — вызов метода, который нужно настроить.
  • value — возвращаемое значение.

Пример:

Calculator calculator = mock(Calculator.class);
when(calculator.add(2, 3)).thenReturn(10);
System.out.println(calculator.add(2, 3)); // 10
System.out.println(calculator.add(1, 1)); // 0 (значение по умолчанию)

3. when().thenThrow() — настройка выброса исключения

Что делает: Указывает, что при вызове метода должно быть выброшено исключение.

Параметры:

  • methodCall — вызов метода.
  • Throwable... toBeThrown — исключение (или несколько) для выброса.

Пример:

UserRepository repo = mock(UserRepository.class);
when(repo.findById(-1L)).thenThrow(new IllegalArgumentException("Invalid ID"));
assertThrows(IllegalArgumentException.class, () -> repo.findById(-1L));

4. verify() — проверка вызова метода

Что делает: Верифицирует, что определенный метод был вызван на mock-объекте с заданными параметрами и определенное количество раз.

Параметры:

  • mock — mock-объект.
  • VerificationMode mode — режим верификации (times(), never(), atLeastOnce() и др.).

Пример:

List<String> list = mock(List.class);
list.add("one");
list.add("two");

verify(list).add("one");           // Проверка, что был вызов с "one"
verify(list, times(1)).add("one"); // Ровно один раз
verify(list, never()).clear();     // Никогда не вызывался
verify(list, atLeastOnce()).add(anyString()); // Хотя бы один раз с любой строкой

5. doReturn().when() — альтернатива when().thenReturn()

Что делает: Используется для настройки void-методов или когда нужно избежать выполнения реального метода (например, при использовании spy).

Параметры: Аналогичны when().thenReturn(), но синтаксис другой.

Пример:

List<String> list = spy(new ArrayList<>());
doReturn(100).when(list).size(); // Переопределяем метод size()
System.out.println(list.size()); // 100

6. spy() — частичное мокирование

Что делает: Создает обертку вокруг реального объекта. По умолчанию вызываются реальные методы, но их можно переопределить с помощью when() или doReturn().

Параметры:

  • Object object — реальный объект для обертки.

Пример:

List<String> realList = new ArrayList<>();
List<String> spyList = spy(realList);

spyList.add("one");
spyList.add("two");
System.out.println(spyList.size()); // 2 (реальный вызов)

doReturn(10).when(spyList).size(); // Переопределяем
System.out.println(spyList.size()); // 10

7. ArgumentCaptor — захват аргументов

Что делает: Позволяет "поймать" аргументы, переданные в mock-метод, для последующей проверки их значений.

Параметры:

  • Class<T> clazz — класс захватываемого аргумента.

Пример:

UserRepository repo = mock(UserRepository.class);
UserService service = new UserService(repo);

service.createUser("Bob");

ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
verify(repo).save(captor.capture());

User capturedUser = captor.getValue();
assertEquals("Bob", capturedUser.getName());

8. @Mock и @InjectMocks — аннотации для упрощения

Что делает: @Mock автоматически создает mock-объект. @InjectMocks создает экземпляр тестируемого класса и внедряет в него mock-зависимости.

Параметры: Аннотации не требуют параметров, но @Mock поддерживает name и answer.

Пример:

@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {

    @Mock
    private PaymentGateway paymentGateway;

    @Mock
    private InventoryService inventoryService;

    @InjectMocks
    private OrderService orderService; // Mock-объекты внедряются автоматически

    @Test
    public void testPlaceOrder() {
        when(inventoryService.isAvailable(anyString())).thenReturn(true);
        when(paymentGateway.charge(anyDouble())).thenReturn(true);

        boolean result = orderService.placeOrder("item123", 100.0);
        assertTrue(result);
    }
}

9. any() / anyInt() / anyString() — гибкие матчеры

Что делает: Позволяют задавать условия для аргументов при настройке или верификации. any() — любой объект, anyInt() — любое целое число и т.д.

Параметры: Не требуют параметров или принимают класс.

Пример:

List<String> list = mock(List.class);
when(list.get(anyInt())).thenReturn("element");

System.out.println(list.get(0));   // "element"
System.out.println(list.get(999)); // "element"

verify(list, times(2)).get(anyInt());

10. reset() — сброс mock-объекта

Что делает: Сбрасывает все настройки и вызовы для mock-объекта. Полезно, если нужно переиспользовать mock в разных тестах.

Параметры:

  • Object... mocks — один или несколько mock-объектов.

Пример:

List<String> list = mock(List.class);
when(list.size()).thenReturn(10);
System.out.println(list.size()); // 10

reset(list);
System.out.println(list.size()); // 0 (сброшено)

Реальный практический пример

Рекомендаций