Go: Автоматическое тестирование
Теория: Мокирование зависимостей через интерфейсы
В любом более-менее серьёзном коде появляются зависимости. Это может быть база данных, HTTP-клиент, файловая система, кэш или внешнее API. В рабочем коде они нужны — но в тестах такие зависимости превращаются в проблему. Поднять настоящую базу? Медленно. Настроить внешний сервис? Ненадёжно, он может быть недоступен. А если тесты начинают реально стучаться в интернет или писать на диск — никакой изоляции уже нет.
Поэтому разработчики придумали подмену зависимостей: вместо реальной базы или API в тестах используется поддельная реализация. В Go это особенно удобно, потому что есть интерфейсы. Код работает через интерфейс, и ему всё равно, кто стоит «за кулисами» — настоящая реализация или подделка.
Эта подделка и есть мок. Он ведёт себя как настоящая зависимость снаружи, но внутри возвращает ровно те ответы, которые нужны тесту.
Интерфейс как контракт
В Go интерфейс — это обещание: «Я умею эти методы». Всё. Конкретно как — решает реализация.
Например, сервис пользователей.
Здесь Service вообще не знает, где лежат пользователи. Он работает только через интерфейс. Это и даёт возможность в тестах подсовывать ему «куклу» вместо настоящего хранилища.
Самый простой мок: жёстко зашитый ответ
Для старта можно сделать совсем простой мок:
Тест с таким моком:
Здесь всё жёстко: любой id возвращает одного и того же юзера. Это примитивно, но иногда этого хватает, чтобы проверить «провода»: что Service вообще вызывает GetUser и достаёт имя.
Более гибкий мок: заранее заданные данные
Чаще нужен контроль над тем, какие id есть, а какие нет. Тогда мок хранит карту пользователей.
Тест с таким моком:
Теперь поведение контролируем полностью: хотим — возвращаем юзера, хотим — ошибку.
Мок как способ эмулировать сбои
Иногда нужно проверить, как сервис ведёт себя при сбоях зависимостей. Например, база «упала».
Тест:
Таким образом можно проверить, что сервис правильно обрабатывает критические ситуации и не падает сам.
Более сложный пример: HTTP-клиент
Возьмём случай, когда сервис делает HTTP-запрос. В боевом коде он использует http.Client, но в тестах мы не хотим ходить в интернет. Как быть?
Определим интерфейс:
Реальный код использует *http.Client, потому что у него есть метод Do. А в тесте можно подставить свой мок:
Тест:
Теперь тесты работают без интернета, быстро и предсказуемо.
Итоги
В Go интерфейсы позволяют легко подменять реальные зависимости на моки. Код работает через контракт (UserStorage, HTTPDoer), и ему всё равно, что стоит за ним. В реальности это база или сеть, в тесте — простая структура с картой или жёстко зашитым ответом.
Моки дают изоляцию, скорость и контроль: можно проверить как успешные сценарии, так и ошибки или сбои. Это делает тесты надёжными, повторяемыми и безопасными.



