sql >> Databasteknik >  >> RDS >> Mysql

Testdriven utveckling för att kontrollera databasfrågor involverade metoder

Jag hade en liknande fråga för inte så länge sedan när jag refaktorerade några av mina egna tester, och det finns ett par sätt du kan göra det på:

a) Ange en exporterad typ och en Open eller Connect funktion som returnerar det - t.ex.

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
}

... och sedan var och en av dina testar, skriv inställnings- och rivningsfunktioner som returnerar en instans av *DB som du definierar dina databasfunktioner på (som metoder - t.ex. 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
}

Observera att detta är något "integreringstestning", men jag föredrar starkt att testa mot en "riktig" databas eftersom hånande av gränssnittet inte hjälper dig att fånga problem med dina frågor/frågesyntax.

b) Alternativet, även om det är mindre utbyggbart på applikationssidan, är att ha en global db *sql.DB variabel som du initierar i init() i dina tester – eftersom tester inte har någon garanterad ordning måste du använda init() —och kör sedan dina tester därifrån. 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 hitta några praktiska exempel i drone.io:s GitHub-repo , och jag skulle också rekommendera den här artikeln om strukturering av Go-applikationer (särskilt DB-grejer).



  1. Oracle datum verkar lika

  2. Hur får man alla inlägg med alla kategorier i wordpress genom mysql?

  3. Använder SqlDataAdapter för att infoga en rad

  4. Hur matchar man element i en array av sammansatt typ?