sql >> Database teknologi >  >> RDS >> Mysql

Testdrevet udvikling for at kontrollere databaseforespørgsler involverede metoder

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



  1. Hvad er fordelen ved at bruge SET XACT_ABORT ON i en lagret procedure?

  2. Global forespørgsel timeout i MySQL 5.6

  3. Hvordan opretter man forbindelse til PostgreSQL fra Phoenix Web App via SSL?

  4. PostgisDialect vs PostgreSQLDialect eller begge dele?