Jeg havde et lignende spørgsmål for ikke længe siden, da jeg refaktorerede nogle af mine egne tests, og der er et par måder, du kan gøre det på:
a) Angiv en eksporteret type og en Open
eller Connect
funktion, der returnerer det - f.eks.
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
}
... og derefter hver af dine test, skriv opsætnings- og nedtagningsfunktioner, der returnerer en forekomst af *DB
som du definerer dine databasefunktioner på (som metoder - dvs. 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
}
Bemærk, at dette er noget "integrationstest", men jeg foretrækker stærkt at teste mod en "rigtig" database, da det at håne grænsefladen ikke hjælper dig med at fange problemer med dine forespørgsler/forespørgselssyntaks.
b) Alternativet, selvom det er mindre udvidelsesvenligt på applikationssiden, er at have en global db *sql.DB
variabel, som du initialiserer i init()
i dine tests – da test ikke har nogen garanteret rækkefølge, skal du bruge init()
-og kør så dine test derfra. dvs.
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)
...
}
Du kan finde nogle praktiske eksempler i drone.io's GitHub-repo , og jeg vil også anbefale denne artikel om strukturering af Go-applikationer (især DB-tingene).