Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Разница между Mock и Stub
Mock и Stub — это два разных типа тестовых двойников (test doubles), используемых в юнит-тестировании. Хотя оба заменяют реальные объекты, они используются для разных целей и имеют существенные различия.
Stub — Заглушка для данных
Stub — это простой объект, который предоставляет фиксированные данные для тестируемого кода. Его основная задача — обеспечить контролируемое состояние.
public interface UserRepository {
User findById(Long id);
}
public class UserRepositoryStub implements UserRepository {
@Override
public User findById(Long id) {
// Всегда возвращает одного и того же пользователя
return new User(1L, "John Doe", "john@example.com");
}
}
@Test
public void testUserService_WithStub() {
UserRepository stub = new UserRepositoryStub();
UserService service = new UserService(stub);
User result = service.getUserInfo(1L);
// Проверяем правильность обработки данных
assertEquals("John Doe", result.getName());
}
Stub:
- Возвращает предопределённые данные
- Не проверяет, как его вызывают
- Используется для изоляции зависимостей
- Простой для написания и понимания
Mock — Проверка поведения
Mock — это объект, который проверяет, как его вызывают. Он фиксирует ожидания (expectations) и позволяет проверить взаимодействие между объектами.
@Test
public void testUserService_WithMock() {
// Используем Mockito
UserRepository mock = mock(UserRepository.class);
// Устанавливаем ожидание
when(mock.findById(1L)).thenReturn(
new User(1L, "John Doe", "john@example.com")
);
UserService service = new UserService(mock);
User result = service.getUserInfo(1L);
// Проверяем результат
assertEquals("John Doe", result.getName());
// Проверяем взаимодействие — mock должен быть вызван ровно один раз
verify(mock, times(1)).findById(1L);
}
Мок:
- Проверяет вызовы и параметры
- Использует verify() для проверки взаимодействия
- Обнаруживает нежелательные вызовы
- Гарантирует, что сотрудничество объектов правильное
Наглядное сравнение
| Аспект | Stub | Mock |
|---|---|---|
| Цель | Предоставить данные | Проверить взаимодействие |
| Проверка | Только результаты | Вызовы и параметры |
| Сложность | Простой | Сложнее |
| Фреймворк | Часто вручную | Mockito, JMock, EasyMock |
| Assert | assertEquals | verify() |
Пример: Отправка Email
public interface EmailService {
void sendEmail(String email, String message);
}
// STUB — не проверяет вызовы
public class EmailServiceStub implements EmailService {
@Override
public void sendEmail(String email, String message) {
// Просто игнорируем, ничего не делаем
}
}
// MOCK — проверяет вызовы
@Test
public void testNotificationService() {
EmailService emailMock = mock(EmailService.class);
NotificationService service = new NotificationService(emailMock);
service.notifyUser("user@example.com", "Welcome!");
// Проверяем, что email был отправлен с правильными параметрами
verify(emailMock).sendEmail(
eq("user@example.com"),
contains("Welcome")
);
}
Когда что использовать
Stub — когда нужны данные для работы тестируемого кода:
- Репозитории, читающие данные
- Конфигурационные сервисы
- Статические данные
Mock — когда нужно проверить взаимодействие:
- Отправка сообщений (email, SMS)
- Логирование
- Вызовы внешних API
- Любая сторона с побочными эффектами
Лучшие практики
- Используй Mock только для проверки взаимодействия
- Используй Stub для изоляции зависимостей
- Не переусложняй — иногда Stub достаточно
- Предпочитай реальные объекты, если быстро стартуют
- Используй фреймворки вроде Mockito для удобства
В современном тестировании обычно используют фреймворк Mockito, который позволяет легко создавать как Stubs (через when/thenReturn), так и Mocks (через verify).