Ответ 1
У меня был аналогичный вопрос недавно, когда рефакторинг некоторых из моих собственных тестов, и есть несколько способов, которыми вы можете это сделать:
a) Предоставьте экспортированный тип и функцию Open
или Connect
которая возвращает его, например:
type DB struct {
db *sql.DB
}
// Using http://jmoiron.github.io/sqlx/ for this example, but
// it has the same interface as database/sql
func Open(opts *Options) (*DB, error) {
db, err := sqlx.Connect(opts.Driver, fmt.Sprintf("host=%s user=%s dbname=%s sslmode=%s", opts.Host, opts.User, opts.Name, opts.SSL))
if err != nil {
return nil, err
}
return &DB{db}, nil
}
... и затем каждый из ваших тестов, напишите функции настройки и разрыва, которые возвращают экземпляр *DB
который вы определяете свои функции базы данных (как методы - например, func (db *DB) GetUser(user *User) (bool, error)
):
// Setup the test environment.
func setup() (*DB, error) {
err := withTestDB()
if err != nil {
return nil, err
}
// testOptions is a global in this case, but you could easily
// create one per-test
db, err := Open(testOptions)
if err != nil {
return nil, err
}
// Loads our test schema
db.MustLoad()
return db, nil
}
// Create our test database.
func withTestDB() error {
db, err := open()
if err != nil {
return err
}
defer db.Close()
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s;", testOptions.Name))
if err != nil {
return err
}
return nil
}
Обратите внимание, что это несколько "интеграционное" тестирование, но я предпочитаю тестировать "настоящую" базу данных, так как насмехающийся интерфейс не поможет вам уладить проблемы с синтаксисом запросов/запросов.
b) Альтернатива, хотя и менее расширяемая на стороне приложения, состоит в том, чтобы иметь глобальную переменную db *sql.DB
которую вы инициализируете в init()
в своих тестах, поскольку тесты не имеют гарантированного порядка, вам нужно будет использовать init()
- и затем выполните тесты оттуда. т.е.
var db *sql.DB
func init() {
var err error
// Note the = and *not* the assignment - we don't want to shadow our global
db, err = sqlx.Connect(...)
if err != nil {
...
}
err := db.loadTestSchema
// etc.
}
func TestGetUser(t *testing.T) {
user := User{}
exists, err := db.GetUser(user)
...
}
Вы можете найти некоторые практические примеры в drone.io GitHub repo, и я также рекомендовал бы эту статью о структурировании приложений Go (особенно данных БД).