Назад к вопросам
Junior
203
questionbank

Что такое mock в тестировании?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Mock-объект (мок) — это имитация реального объекта или зависимости в модульном тесте. Он используется для изоляции тестируемого компонента путем замены его зависимостей подконтрольными заглушками.

Основные цели использования моков:

  • Изоляция: Тестирование только конкретного класса или метода, без учета поведения его зависимостей.
  • Контроль: Возможность задать ожидаемое поведение зависимостей (возвращаемые значения, выбрасываемые исключения, количество вызовов методов) в различных тестовых сценариях.
  • Ускорение: Избегание выполнения ресурсоемких или медленных операций реальных зависимостей (например, работа с базой данных, сетевые вызовы).
  • Тестирование исключительных ситуаций: Простое моделирование ошибок или нестандартного поведения зависимостей, которое сложно воспроизвести с реальными объектами.

Типы "двойников" в тестировании (заглушек, моков и т.д.):

  • Dummy: Передаются как аргументы, но не используются.
  • Fake: Имеют рабочую реализацию, но упрощенную (например, база данных в оперативной памяти).
  • Stub: Предоставляют предопределенные ответы на вызовы методов, но не проверяют их взаимодействие.
  • Spy: По сути, это Stub, который также записывает информацию о вызовах методов (сколько раз, с какими аргументами).
  • Mock: Заранее определяют ожидаемое поведение (ожидаемые вызовы методов с ожидаемыми аргументами) и при этом выполняют проверку этого поведения в конце теста.

Библиотеки для создания моков в Java:

  • Mockito
  • EasyMock
  • PowerMock (для статических, приватных методов и конструкторов)

Пример использования Mockito:

// Класс, который мы хотим протестировать
class MyService {
    private Dependency dependency;

    public MyService(Dependency dependency) {
        this.dependency = dependency;
    }

    public String processData(String data) {
        String processed = dependency.process(data);
        if (processed != null && processed.startsWith("OK")) {
            return "Success: " + processed;
        } else {
            return "Failure";
        }
    }
}

// Зависимость, которую мы будем мокать
interface Dependency {
    String process(String input);
}

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

class MyServiceTest {

    @Test
    void testProcessDataSuccess() {
        // Создаем мок объекта Dependency
        Dependency mockDependency = mock(Dependency.class);

        // Задаем ожидаемое поведение мока: при вызове process("input") вернуть "OK: data"
        when(mockDependency.process("input")).thenReturn("OK: data");

        // Создаем тестируемый объект с моком в качестве зависимости
        MyService myService = new MyService(mockDependency);

        // Выполняем тестируемый метод
        String result = myService.processData("input");

        // Проверяем результат
        assertEquals("Success: OK: data", result);

        // Проверяем, что метод process мока был вызван ровно один раз с аргументом "input"
        verify(mockDependency, times(1)).process("input");
    }

    @Test
    void testProcessDataFailure() {
        // Создаем мок объекта Dependency
        Dependency mockDependency = mock(Dependency.class);

        // Задаем ожидаемое поведение мока: при вызове process("input") вернуть "Error"
        when(mockDependency.process("input")).thenReturn("Error");

        // Создаем тестируемый объект с моком в качестве зависимости
        MyService myService = new MyService(mockDependency);

        // Выполняем тестируемый метод
        String result = myService.processData("input");

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

        // Проверяем, что метод process мока был вызван ровно один раз с аргументом "input"
        verify(mockDependency, times(1)).process("input");
    }
}

В итоге, моки позволяют создавать предсказуемые и управляемые тестовые сценарии, что критически важно для надежного модульного тестирования.