Ответ
И моки, и стабы являются тестовыми двойниками (test doubles), которые используются для изоляции тестируемого компонента от его зависимостей. Ключевое различие заключается в цели их использования и способе проверки.
Стабы (Stubs)
Цель: Предоставить заранее заготовленные данные для тестируемого кода. Стабы используются для проверки состояния (state verification).
Вы проверяете, что ваш код, получив определённые данные от зависимости, возвращает правильный результат или меняет своё состояние корректным образом.
Пример: Мы тестируем функцию, которая получает пользователя из базы данных и форматирует его имя. Нам не важна реализация БД, нам просто нужно, чтобы она вернула пользователя.
// Зависимость, которую мы заменяем стабом
// type UserProvider interface {
// GetUser(id int) (*User, error)
// }
// Простой стаб, который всегда возвращает одного и того же пользователя
type DBStub struct{}
func (d *DBStub) GetUser(id int) (*User, error) {
// Возвращаем заранее определённые данные
return &User{ID: id, Name: "Test User"}, nil
}
Моки (Mocks)
Цель: Проверить, что тестируемый код правильно взаимодействует со своими зависимостями. Моки используются для проверки поведения (behavior verification).
Вы проверяете, что ваш код вызвал нужные методы зависимости, с правильными аргументами и в правильном порядке.
Пример: Мы тестируем функцию, которая при регистрации пользователя должна не только создать его в БД, но и отправить email. Мы хотим убедиться, что метод отправки email был вызван ровно 1 раз с правильным адресом.
// Используем популярную библиотеку testify/mock
import "github.com/stretchr/testify/mock"
// Мок-объект для сервиса уведомлений
type NotificationServiceMock struct {
mock.Mock
}
func (m *NotificationServiceMock) SendWelcomeEmail(email string) error {
// Регистрируем вызов и его аргументы
args := m.Called(email)
// Возвращаем то, что было настроено в тесте
return args.Error(0)
}
// В тесте:
mockService := new(NotificationServiceMock)
// Ожидаем, что метод SendWelcomeEmail будет вызван 1 раз с аргументом "test@example.com"
mockService.On("SendWelcomeEmail", "test@example.com").Return(nil).Once()
// ... вызываем тестируемую функцию ...
// Проверяем, что все ожидания оправдались
mockService.AssertExpectations(t)
Ключевые отличия в таблице:
Характеристика | Стаб (Stub) | Мок (Mock) |
---|---|---|
Основная цель | Подменить зависимость для предоставления данных | Проверить правильность взаимодействия с зависимостью |
Что проверяет | Конечное состояние системы (State Verification) | Последовательность и параметры вызовов (Behavior Verification) |
Сложность | Обычно проще, реализуется вручную | Часто требует библиотек (testify/mock ), сложнее в настройке |
Итог: Используйте стабы, когда вам нужно просто "заткнуть" зависимость данными. Используйте моки, когда вам критически важно проверить, как именно ваш код взаимодействует с зависимостью.