sql >> Database >  >> RDS >> Mysql

Testgestuurde ontwikkeling om de betrokken methoden voor databasequery's te controleren

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).



  1. Probleem met JPA-project in Eclipse - fout in klasse geannoteerd @Entity:Tabel xxx kan niet worden opgelost

  2. MYSQL INSERT of UPDATE IF

  3. Fix Error "ORA-01789:queryblok heeft een onjuist aantal resultaatkolommen"

  4. Schemapatroon zoeken naar gegevensklasse-associatie