Go: запустить тест из нескольких пакетов с инициализацией БД

У меня есть проект GO с такой структурой проекта (несколько пар файлов такого типа в каждом пакете).

- api
    - userHandler.go
    - userHandler_test.go
- database
    - user.go
    - user_test.go

Внутри user.go у меня есть структура User и функции для создания / получения / обновления пользователя (я использую GORM, но это не проблема). В user_test.go.

Я хотел бы очистить БД (со всеми данными, удаленными или в определенном состоянии) для каждого отдельного файла, поэтому я попытался создать 1 комплект (используя Testify) для каждого файла, затем использовать функцию SetupSuite, но поведение кажется не детерминированным, и, вероятно, я делаю что-то не так.

Итак, мои вопросы:

  • Какой лучший способ иметь соединение с БД? Использование глобальной переменной является лучшим вариантом?
  • Каков наилучший способ создать таблицы в БД один раз, а затем инициализировать БД с пользовательскими данными перед каждым запуском file_test.go?

Прямо сейчас у меня тоже странная ошибка: бег

go test path/package1
go test path/package2

Все отлично работает, но если я запустлю (для тестирования всех пакетов)

cd path && go test ./...

У меня есть ошибки, которые не являются детерминированными, поэтому я предполагаю, что соединение с БД не обрабатывается должным образом

1 ответ

Решение

Если твой api пакет зависит от вашего database пакет (который кажется), то ваш api пакет должен иметь способ предоставить пул соединений с базой данных (например, *sql.DB) к нему.

В ваших тестах на api пакет, вы должны просто передать в инициализированный пул (возможно, с предварительно заполненной тестовой схемой / приборами), который вы можете использовать. Это может быть глобальная инициализация в init() для api пакет или setup() а также defer teardown() шаблон в каждой тестовой функции.

Вот первый (самый простой) подход, когда вы просто создаете общую базу данных и схему для своих тестов.

package database

import testing

var testDB *sql.DB

// This gets run before your actual test functions do.
func init() {
    var err error
    db, err = sql.Open(...)
    if err != nil {
        log.Fatalf("test init failed: %s", err)
    }

    _, err := db.Exec(`CREATE TABLE ....`)
    if err != nil {
        log.Fatalf("test schema creation failed: %s", err)
    }
}

Несколько советов:

  • Вы также можете позвонить setup() Функция может создать таблицу со случайным суффиксом и вставить ваши тестовые данные, чтобы ваши тесты не использовали одну и ту же тестовую таблицу (и, следовательно, рискуют конфликтовать или полагаться друг на друга). Захватите это имя таблицы и поместите его в свой defer teardown() функция.
  • https://medium.com/@benbjohnson/structuring-applications-in-go-3b04be4ff091 стоит прочитать для некоторых дополнительных перспектив.
Другие вопросы по тегам