TGViewer
Библиотека Go-разработчика | Golang Библиотека Go-разработчика | Golang @goproglib · 24.1K subscribers
Post #7291 2.8K
🧑‍💻 Монолитные тесты Go API: почему один файл душит проект

Когда проект на Go растёт, тесты часто скатываются в один гигантский *_test.go. В него свалено всё подряд. Настройка окружения, рукописные моки репозитория и сервиса, проверка бизнес логики, симуляция HTTP. Сначала удобно, потом файл пухнет до тысяч строк. В этой части разберём, чем это плохо и как вынести моки в одно место.

⚙️ Две боли монолита

Первое, разрастание кода. Файл с сетапом, табличными кейсами и подробными моками превращается в нечитаемое полотно, по которому невозможно навигироваться.

Второе, циклические импорты. В Go пакеты не могут импортировать друг друга по кругу. Когда моки, доменная логика и HTTP транспорт плотно связаны в тестах, границы между пакетами базы, сервиса и хендлера размываются, и компилятор падает с ошибкой циклической зависимости.

⚙️ Решение — разделить по ответственности

Монолит разбивается на три файла внутри тестового пакета:
package_test/
mock.go // общие моки сервиса и репозитория
*_service_test.go // юнит тесты бизнес логики
*_handler_test.go // HTTP, роутинг, валидация


Моки в одном месте

Вместо копипаста по разным файлам все структуры заглушек объявляются один раз в отдельном mock.go. Это единый источник правды для тестовых дублей, и именно вынос моков убирает циклические импорты:
type MockAuthRepository struct {
GetUsernameOrEmailFunc func(ctx context.Context, username string) (*models.Users, error)
RegisterFunc func(ctx context.Context, user *models.Users) error
}

func (m *MockAuthRepository) GetUsernameOrEmail(ctx context.Context, username string) (*models.Users, error) {
if m.GetUsernameOrEmailFunc != nil {
return m.GetUsernameOrEmailFunc(ctx, username)
}
return &models.Users{}, nil
}


Один файл с тестами это удобный старт и плохой финал. Разрастание кода и циклические импорты лечатся выносом моков в mock.go и разбиением тестов на слои. В части 2 покажем тесты бизнес логики и HTTP слоя, а также трейдоффы подхода.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoToProduction
  • 👍 4
  • ❤ 3
More from @goproglib
  1. Sep 28, 2026🤔 Вопрос с собеседования по Go Что выведет программа? ❤️ — 1 true / 0 false 🔥 — 1 true /…
  2. Sep 28, 2026👩‍💻 Что на самом деле происходит внутри Go map? После Go 1.24 обычный map внутри работае…
  3. Sep 26, 2026🔥 В Go 1.27 появился portable SIMD До этого SIMD-оптимизации в Go требовали архитектурног…
  4. Sep 25, 2026🤡🤡 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека Go-разработчика #GoGiggle
  5. Sep 25, 2026💡 Код работает. А data race уже есть В Go можно записать значение в одной горутине, прочи…
  6. Sep 23, 2026💥 TCP/IP: что происходит с данными в сети Когда Go-приложение отправляет данные по сети,…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →