Ответ
Плюсы стабов:
- Изоляция и контроль данных: Стаб заменяет реальную зависимость и возвращает заранее заданные, предсказуемые данные. Это позволяет тестировать реакцию системы на конкретные входные данные (как валидные, так и ошибочные).
- Ускорение тестов: Как и моки, стабы исключают медленные операции (запросы к БД, внешние API).
- Детерминированность: Поведение стаба всегда одинаково, что делает тесты стабильными и воспроизводимыми.
- Простота создания: Стабы часто проще создать, чем моки, так как их основная задача — возвращать данные, а не отслеживать взаимодействия.
- Тестирование граничных условий и ошибок: Легко сымитировать ситуацию, когда зависимость возвращает
null, пустой список, бросает исключение или отвечает с задержкой.
Минусы стабов:
- Не проверяют взаимодействие: В отличие от мока, стаб обычно не позволяет проверить, был ли вызван метод зависимости. Он только предоставляет данные.
- Риск расхождения с реальностью: Если поведение реальной зависимости изменилось (например, изменился формат JSON-ответа), стаб, возвращающий старые данные, не позволит это обнаружить, что приведет к ложному прохождению unit-теста и возможному падению в продакшене.
- Дополнительная нагрузка на поддержку: При изменении интерфейса зависимости все ее стабы в тестах требуют обновления.
- Могут маскировать проблемы интеграции: Успешные тесты со стабами создают иллюзию работоспособности, в то время как реальное соединение между системами может быть broken.
Пример использования стаба для тестирования репозитория (Python/unittest):
# Реальный класс, который мы тестируем
class UserReportGenerator:
def __init__(self, user_repository):
self.user_repo = user_repository
def generate_active_users_report(self):
all_users = self.user_repo.get_all_users() # Зависимость от репозитория
active_users = [u for u in all_users if u.is_active]
return f"Active users: {len(active_users)}"
# Тест со стабом
from unittest.mock import Mock
def test_generate_active_users_report():
# 1. Создаем стаб репозитория
stub_repository = Mock()
# 2. Настраиваем стаб на возврат конкретных данных
fake_users = [
Mock(is_active=True, name="Alice"),
Mock(is_active=False, name="Bob"),
Mock(is_active=True, name="Charlie")
]
stub_repository.get_all_users.return_value = fake_users
# 3. Инжектируем стаб в тестируемый объект
generator = UserReportGenerator(stub_repository)
# 4. Выполняем тест и проверяем результат
report = generator.generate_active_users_report()
# Проверяем логику обработки данных, а не вызов метода
assert report == "Active users: 2"
# Примечание: мы НЕ проверяем, был ли вызван get_all_users.
# Это был бы уже мок, а не стаб.