miałem podobne pytanie nie tak dawno temu, gdy refactoring niektóre z moich własnych badań, a tam kilka sposobów można to zrobić:
a) Zapewnienie eksportowany typ oraz Open
lub Connect
funkcję, która zwraca go - np
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
}
... a potem każdego z testów, zapisu konfiguracji & funkcje przerywaniem które zwracają wystąpienie *DB
które określają swoje funkcje bazy danych na (jako metody - tj 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
}
Należy zauważyć, że jest to test "integracyjny", ale zdecydowanie preferuję testowanie z "prawdziwą" bazą danych, ponieważ kpiny z interfejsu nie pomogą w wychwyceniu problemów z składnią zapytań/zapytań.
b) alternatywa, chociaż mniej rozszerzalny na stronie aplikacji, ma mieć zmienną globalną db *sql.DB
że uruchamiasz w init()
w swoich badaniach, ponieważ testy nie mają zagwarantowaną kolejność będzie trzeba użyć init()
-i następnie uruchomić twoje testy z tego miejsca. tj
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)
...
}
Można znaleźć kilka praktycznych przykładów w drone.io's GitHub repo, a ja również polecam this article on structuring Go applications (zwłaszcza rzeczy dB).
Myślę, że powinieneś kpić z warstwy dostępu do danych. – RoninDev
To jest to, co zrobiłem na końcu - https://github.com/sumitasok/go-test-db. Proszę, obrzuć mnie swoimi myślami. Wkrótce dodam plik Readme. –
Istnieje https://github.com/DATA-DOG/go-sqlmock właśnie dla tego, który jest sterownik sql iw pełni symuluje bazę danych bez rzeczywistego połączenia. – Gediminas