Короткий ответ
Решение зависит от стоимости и стабильности реальной зависимости: для быстрых и детерминированных зависимостей (своя тестовая БД, внутренний сервис с тестовым окружением) стоит тестировать против реальных инстансов в интеграционных тестах, а для медленных, дорогих, нестабильных или сторонних зависимостей (внешние платёжные шлюзы, сторонние API с лимитами) оправданы моки и контрактные тесты вместо постоянных реальных вызовов в CI.
Как это работает подробнее
Моки дают скорость, детерминированность и независимость от доступности внешней системы, но верны ровно настолько, насколько верны предположения разработчика о поведении реальной зависимости — если реальный сервис изменит поведение, мок этого не заметит. Реальные зависимости в CI (через контейнеры или тестовые окружения) дают более высокую уверенность, но увеличивают время прогона, хрупкость (сетевые сбои, лимиты) и инфраструктурную сложность пайплайна.
Сравнение
- Компромисс. Больше моков — быстрый и стабильный CI, но риск расхождения мока с реальным поведением зависимости со временем. Больше реальных вызовов — выше доверие к результату, но дороже, медленнее и менее предсказуемо (зависимость от сети и SLA третьей стороны). Критерий выбора: стоимость ложного отрицательного результата (пропущенной поломки интеграции) против стоимости медленного и нестабильного CI — для критичных денежных интеграций стоит инвестировать в периодические реальные smoke-тесты вдобавок к мокам, даже если они не гоняются на каждый коммит.
Пример кода
Стратегия для интеграции с внешним платёжным шлюзом:
- unit-тесты бизнес-логики: мок платёжного клиента (каждый коммит, секунды)
- контрактные тесты: записанные реальные ответы шлюза через VCR-кассеты (каждый коммит)
- smoke-тест в песочнице шлюза: один реальный платёж в тестовом режиме
(по расписанию раз в сутки, не блокирует обычный релиз)Что использовать на практике
- Практика. Распространённый компромисс — трёхуровневая стратегия: unit-тесты с моками для быстрой обратной связи по логике, контрактные тесты против записанных или согласованных реальных ответов (VCR-кассеты, Pact) для проверки формата без постоянных реальных вызовов, и небольшое число настоящих end-to-end smoke-тестов против реальной (тестовой) внешней системы, запускаемых реже — например, по расписанию, а не на каждый коммит.
Подводные камни
- Риск. Мокать внешнюю зависимость один раз на старте проекта и никогда не обновлять мок при изменении реального API, из-за чего моки медленно расходятся с реальностью и тесты теряют ценность, оставаясь зелёными при реально сломанной интеграции. Либо обратная крайность — тестировать абсолютно всё против реальных внешних сервисов в каждом CI-прогоне, что делает пайплайн медленным, дорогим и зависимым от доступности третьих сторон.