Ответ
Мокирование в Go — это ключевая техника для написания изолированных юнит-тестов. Его основная цель — заменить реальные зависимости (например, базу данных или внешний API) на контролируемые тестовые двойники (моки).
В Go это достигается преимущественно через интерфейсы.
Подходы к мокированию:
-
Ручное мокирование Простой способ, при котором вы вручную создаете структуру, реализующую нужный интерфейс. Подходит для простых интерфейсов.
// Интерфейс нашей зависимости type UserStorage interface { GetUser(id int) (string, error) } // Ручной мок type MockUserStorage struct { User string Error error } func (m *MockUserStorage) GetUser(id int) (string, error) { return m.User, m.Error } // Тест, использующий мок func TestUserService(t *testing.T) { mockDB := &MockUserStorage{User: "test_user", Error: nil} service := NewUserService(mockDB) // ... дальнейшее тестирование логики сервиса }
-
Автоматическая генерация моков Для сложных интерфейсов ручное создание моков становится утомительным. Здесь помогают инструменты кодогенерации.
Популярные инструменты:
-
gomock
(от Google): Официальный и очень мощный инструмент. Он генерирует моки из интерфейсов с помощью утилитыmockgen
. Его особенность — строгий контроль вызовов черезcontroller
.// Пример теста с gomock ctrl := gomock.NewController(t) defer ctrl.Finish() mockDB := NewMockUserStorage(ctrl) // Сгенерированный мок mockDB.EXPECT().GetUser(1).Return("test_user", nil).Times(1) service := NewUserService(mockDB) // ...
-
testify/mock
: Часть популярной библиотекиtestify
. Более гибкий и менее строгий, чемgomock
. Не требует обязательной кодогенерации (хотя отлично работает в паре сmockery
), что делает его проще для старта. -
mockery
: Утилита для генерации моков, которая отлично интегрируется сtestify/mock
.
Ключевой вывод: Независимо от инструмента, основа хорошего мокирования в Go — это проектирование кода с использованием интерфейсов для отделения бизнес-логики от ее зависимостей.