Ik had niet zo lang geleden een soortgelijke vraag toen ik een aantal van mijn eigen tests refactoreerde, en er zijn een aantal manieren waarop je dit kunt doen:
a) Geef een geëxporteerd type en een Open
. op of Connect
functie die het teruggeeft - bijv.
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
}
... en dan elk van je tests, schrijf setup- en demontagefuncties die een instantie van *DB
. retourneren waarop u uw databasefuncties definieert (als methoden - d.w.z. 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
}
Merk op dat dit een beetje een "integratietest" is, maar ik geef er de voorkeur aan om te testen met een "echte" database, aangezien het bespotten van de interface je niet zal helpen problemen met je query's/querysyntaxis op te sporen.
b) Het alternatief, hoewel minder uitbreidbaar aan de kant van de applicatie, is om een globale db *sql.DB
te hebben variabele die u initialiseert in init()
binnen uw tests - aangezien tests geen gegarandeerde volgorde hebben, moet u init()
gebruiken -en voer dan uw tests vanaf daar uit. d.w.z.
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)
...
}
U kunt enkele praktische voorbeelden vinden in drone.io's GitHub-repo , en ik zou ook dit artikel over het structureren van Go-applicaties aanraden (vooral de DB-dingen).