Что такое Mock-объект в тестировании?

«Что такое Mock-объект в тестировании?» — вопрос из категории Тестирование, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Mock-объект — это специально созданный объект-заглушка, который имитирует поведение реальной зависимости в модульном тесте. Его ключевая особенность — возможность проверки взаимодействий: тест может утверждать, что определенные методы мока были вызваны с ожидаемыми аргументами нужное количество раз.

Зачем это нужно? Чтобы изолировать тестируемый модуль (например, сервис) от внешних систем (база данных, API, файловая система) и сосредоточиться на проверке его бизнес-логики.

Пример на Java с Mockito: Допустим, у нас есть NotificationService, который зависит от EmailSender.

// Класс, который мы тестируем
public class NotificationService {
    private EmailSender emailSender;

    public NotificationService(EmailSender emailSender) {
        this.emailSender = emailSender;
    }

    public void sendWelcomeEmail(String userEmail) {
        String subject = "Welcome!";
        String body = "Thank you for registering.";
        emailSender.sendEmail(userEmail, subject, body); // Взаимодействие с зависимостью
    }
}

// Тест с использованием Mock
import static org.mockito.Mockito.*;

class NotificationServiceTest {
    @Test
    void sendWelcomeEmail_ShouldCallEmailSenderWithCorrectParameters() {
        // 1. Создаем mock-объект
        EmailSender mockEmailSender = mock(EmailSender.class);
        NotificationService service = new NotificationService(mockEmailSender);

        String testEmail = "user@example.com";

        // 2. Выполняем действие
        service.sendWelcomeEmail(testEmail);

        // 3. Верификация (VERIFY): проверяем, что взаимодействие произошло
        // Это главное отличие Mock от Stub. Мы проверяем, был ли вызван метод sendEmail
        // с конкретными аргументами ровно один раз.
        verify(mockEmailSender, times(1))
                .sendEmail(eq(testEmail), eq("Welcome!"), contains("Thank you"));
    }
}

Отличие от других типов тестовых дублеров:

  • Stub: Простая заглушка, которая возвращает предопределенные данные. Не занимается верификацией вызовов.
  • Fake: Упрощенная, но рабочая реализация (например, репозиторий, хранящий данные в памяти HashMap вместо реальной БД). Используется для интеграционного тестирования.
  • Spy: Частичный mock, который оборачивает реальный объект, позволяя отслеживать его вызовы и при необходимости подменять поведение отдельных методов.

Использование моков делает unit-тесты быстрыми, стабильными и сфокусированными исключительно на коде, который мы хотим проверить.