Ответ
Плюсы моков:
- Полная изоляция теста: Мок заменяет реальную внешнюю зависимость (базу данных, API, файловую систему), позволяя тестировать только бизнес-логику модуля. Это чистейшая форма unit-теста.
- Контроль над поведением и состоянием: Можно легко сымитировать любые сценарии — успешное выполнение, исключения, таймауты, возврат специфических данных — что сложно или невозможно воспроизвести с реальной зависимостью.
- Скорость: Тесты, не выполняющие сетевые запросы или операции ввода-вывода, выполняются на порядки быстрее.
- Упрощение отладки: Поскольку поведение зависимости предсказуемо и контролируемо, найти причину падения теста проще.
- Верификация взаимодействий: Моки позволяют проверить, был ли вызван метод зависимости, с какими аргументами и сколько раз. Это полезно для тестирования side effects.
Минусы моков:
- Риск ложного прохождения: Тест может проходить с моком, но падать в реальной среде из-за несоответствия поведения мока и реальной системы (например, изменился формат ответа API).
- Сложность поддержки: При изменении интерфейса зависимости (сигнатуры метода) необходимо обновить все моки, что может быть трудоемко.
- Избыточная специфичность: Тест может стать слишком хрупким, если проверяет не что делает система, а как она это делает (например, точную последовательность внутренних вызовов).
- Отсутствие проверки интеграции: Моки не тестируют реальное взаимодействие между компонентами. Для этого нужны интеграционные тесты.
Пример использования мока для тестирования сервиса уведомлений (Java/Mockito):
// Класс, который мы тестируем
public class OrderService {
private NotificationService notificationService;
public OrderService(NotificationService notificationService) {
this.notificationService = notificationService;
}
public void processOrder(Order order) {
// ... логика обработки заказа ...
notificationService.sendEmail(order.getUserEmail(), "Your order is processed");
}
}
// Сам тест
@Test
public void processOrder_ShouldSendNotification() {
// 1. Создаем мок зависимости
NotificationService mockNotificationService = Mockito.mock(NotificationService.class);
OrderService orderService = new OrderService(mockNotificationService);
Order testOrder = new Order("user@example.com");
// 2. Выполняем тестируемое действие
orderService.processOrder(testOrder);
// 3. Верифицируем, что мок был вызван с ожидаемыми аргументами
Mockito.verify(mockNotificationService)
.sendEmail("user@example.com", "Your order is processed");
}