Ответ
Мокирование в 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 — это проектирование кода с использованием интерфейсов для отделения бизнес-логики от ее зависимостей.