Ответ
Моки (mock-объекты) — это специальные объекты-заглушки, которые имитируют поведение реальных зависимостей в изолированной среде. Они являются частью более широкой концепции тестовых двойников (Test Doubles).
Моки используются в юнит- и интеграционном тестировании для замены сложных, медленных или недоступных зависимостей, таких как базы данных, внешние API, файловая система или другие сервисы.
Основные цели использования моков:
- Изоляция: Позволяют тестировать один компонент (например, сервис), не затрагивая его зависимости. Это гарантирует, что тест провалится только из-за ошибки в тестируемом коде, а не во внешней системе.
- Эмуляция сценариев: Дают возможность имитировать любое поведение зависимости: успешный ответ, различные виды ошибок (сетевая, "не найдено"), задержки ответа.
- Ускорение тестов: Замена реальных сетевых вызовов или обращений к диску на быстрые вызовы в памяти значительно сокращает время выполнения тестов.
- Проверка взаимодействий: Моки позволяют проверить, что тестируемый код правильно взаимодействует со своей зависимостью — например, вызывает нужный метод с правильными аргументами.
Пример мока в Go с использованием testify/mock
:
// Интерфейс, который мы будем мокировать
type DBLayer interface {
GetUser(id int) (*User, error)
}
// Структура мока
type MockDB struct {
mock.Mock
}
// Реализация метода интерфейса для мока
func (m *MockDB) GetUser(id int) (*User, error) {
// .Called() регистрирует вызов и возвращает заранее заданные значения
args := m.Called(id)
// Безопасно извлекаем результаты
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*User), args.Error(1)
}
// Тест, использующий мок
func TestUserService(t *testing.T) {
// 1. Создаем экземпляр мока
mockDB := new(MockDB)
// 2. Настраиваем ожидаемое поведение: при вызове GetUser(1) вернуть юзера и nil-ошибку
mockDB.On("GetUser", 1).Return(&User{Name: "John"}, nil)
// 3. Внедряем мок в тестируемый сервис
service := NewUserService(mockDB)
user, err := service.FetchUser(1)
// 4. Проверяем результат
assert.NoError(t, err)
assert.Equal(t, "John", user.Name)
// 5. Убеждаемся, что все настроенные ожидания были выполнены
mockDB.AssertExpectations(t)
}
В итоге, моки — это мощный инструмент для написания надежных, быстрых и предсказуемых тестов.