Моки и gomock
Тема дорожной карты · Golang
Мокирование в Go-тестах — практика замены реальных зависимостей (баз данных, HTTP-клиентов, gRPC-сервисов) управляемыми заменителями, возвращающими предсказуемые значения, что обеспечивает истинное юнит-тестирование Golang-кода в изоляции. Пакет testify/mock из github.com/stretchr/testify предоставляет гибкий API, где mock.On("MethodName", args).Return(values) задаёт ожидания, а mock.AssertExpectations(t) проверяет их после теста. gomock, генерируемый через mockgen -source=interface.go, создаёт типобезопасные mock-структуры, которые компилятор Go проверяет при go build, обнаруживая расхождение интерфейсов на раннем этапе. Мокирование в Go-тестах наиболее эффективно, когда код пишется против интерфейсов: сервис, принимающий io.Reader или пользовательский интерфейс UserRepository, может тестироваться с mock без запуска PostgreSQL, Docker или реального gRPC-сервера. Комбинация мокирования с table-driven тестами и race detector (go test -race) создаёт комплексный, быстрый Golang-тестовый набор, обнаруживающий баги конкурентности и регрессии.
Как это работает
Моки и gomock использует stdlib testing-пакет — фреймворк не нужен. Файлы заканчиваются на _test.go; тесты — func TestX(t *testing.T); subtests через t.Run. Table-driven тесты — идиоматический паттерн. Бенчмарки: func BenchmarkX(b *testing.B), запуск go test -bench=.. Моки: опирайтесь на маленькие интерфейсы (Go-интерфейсы duck-typed — легко заменить stub); gomock или mockery — для генерируемых моков. testify — для fluent-ассертов, httptest — для тестов HTTP-handlers.
Когда применять
Table-driven тесты — дефолт: читаемы, легко добавить кейсы. httptest.Server — для тестов HTTP-клиентов; httptest.ResponseRecorder — для тестов handlers. В CI — с -race. testify — если команда предпочитает fluent-ассерты; иначе stdlib t.Errorf достаточен. dockertest или testcontainers-go — для тестов с реальной БД.
Типичные ошибки
Ловушки Моки и gomock: параллельные тесты (t.Parallel()), делящие state (тонкие race conditions); бенчмарки, оптимизируемые компилятором (присваивайте результаты пакетной sink-переменной); нет -race в CI (data race проскакивают в production); over-mocking — тесты проверяют детали реализации, не поведение.