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