Перейти к содержанию

Тестирование

Что такое моки, зачем они нужны и где используются?

Mock-object (мок-объект или просто "мок") имеет наиболее близкое по смыслу слово — "заглушка".

Для тестов в проекте такие "заглушки" позволяют протестировать какую-либо структуру данных, не собирая для неё все зависимости.

Например:

type logger interface {
	Log(level log.Level, keyvals ...interface{}) error
}

type sender interface {
	Send(ctx context.Context, signal string) error
}

type Notifier struct {
	sender sender
	logger logger
}

func New(logger logger) *Notifier {
	return &Notifier{logger: logger}
}

func (n *Notifier) NotifyAboutRain(ctx context.Context) error {
	err := n.sender.Send(ctx, "It's raining now!")
	if err != nil {
		_ = n.logger.Log(log.LevelError, log.DefaultMessageKey, "failed to send notify about rain")
	} else {
		_ = n.logger.Log(log.LevelInfo, log.DefaultMessageKey, "notify about rain was successfully sent")
	}
	return err
}

В коде выше структура Notify зависит от интерфейсов sender и logger.

Чтобы проверить корректность метода NotifyAboutRain(ctx context.Context) error нет необходимости использовать настоящую структуру для логирования, можно использовать заглушку:

type Logger struct {}

func (l *Logger) Log(log.Level, ...interface{}) error {
	return nil
}

Такая заглушка позволит не беспокоиться о деталях работы логгера и проверить только необходимое.

В проекте используется библиотека github.com/matryer/moq для генерации простых моков, она позволяет по интерфейсу создать минимальную структуру-заглушку, к которой можно выстраивать технические ожидания о вызове конкретных методов, количестве и параметрах таких вызовов.

В проекте будут встречаться комментарии вида:

//go:generate moq -pkg mocks -skip-ensure -out mocks/tag_repository.go . tagRepository:TagRepository

Эти комментарии позволяют по команде make generate генерировать моки по указанным параметрам.

В примере выше указано два интерфейса — logger и sender, они являются зависимостями для структуры Notifier.

В проекте принято такие зависимости выносить в файл dependencies.go и использовать комментарии //go:generate moq в таких файлах.

Пример использования моков в тестах — тесты в пакете internal/biz/cargo, проверяющие корректность интеграции.

Непосредственно сами тесты располагаются в файле internal/biz/cargo/integration_test.go