2014-07-18 11 views
5

Chcę utworzyć aplikację opartą na bazie danych za pomocą programu Golang. Próbuję to zrobić TDD sposób. Kiedy próbuję przetestować metody, które tworzą zapytania SQL, Jakie są dostępne pakiety?Tworzenie testów kierowanych przez firmę Golang w celu sprawdzenia zapytań dotyczących baz danych zaangażowanych metod

  • Nie chcę się łączyć z domyślną bazą danych, której używam do programowania. Mogę napisać kod, aby przejąć inną testową bazę danych podczas uruchamiania testu, ale jest tam jakaś biblioteka, która już to robi.

  • Czy istnieje jakaś biblioteka, która wykonuje testy db bez łączenia się z bazą danych?

Jaki jest standardowy sposób wykonywania testu bazy danych za pomocą golang?

+2

Myślę, że powinieneś kpić z warstwy dostępu do danych. – RoninDev

+0

To jest to, co zrobiłem na końcu - https://github.com/sumitasok/go-test-db. Proszę, obrzuć mnie swoimi myślami. Wkrótce dodam plik Readme. –

+0

Istnieje https://github.com/DATA-DOG/go-sqlmock właśnie dla tego, który jest sterownik sql iw pełni symuluje bazę danych bez rzeczywistego połączenia. – Gediminas

Odpowiedz

13

miałem podobne pytanie nie tak dawno temu, gdy refactoring niektóre z moich własnych badań, a tam kilka sposobów można to zrobić:

a) Zapewnienie eksportowany typ oraz Open lub Connect funkcję, która zwraca go - np

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 
} 

... a potem każdego z testów, zapisu konfiguracji & funkcje przerywaniem które zwracają wystąpienie *DB które określają swoje funkcje bazy danych na (jako metody - tj 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 
} 

Należy zauważyć, że jest to test "integracyjny", ale zdecydowanie preferuję testowanie z "prawdziwą" bazą danych, ponieważ kpiny z interfejsu nie pomogą w wychwyceniu problemów z składnią zapytań/zapytań.

b) alternatywa, chociaż mniej rozszerzalny na stronie aplikacji, ma mieć zmienną globalną db *sql.DB że uruchamiasz w init() w swoich badaniach, ponieważ testy nie mają zagwarantowaną kolejność będzie trzeba użyć init() -i następnie uruchomić twoje testy z tego miejsca. tj

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

Można znaleźć kilka praktycznych przykładów w drone.io's GitHub repo, a ja również polecam this article on structuring Go applications (zwłaszcza rzeczy dB).

+0

To jest to, co zrobiłem na końcu - https://github.com/sumitasok/go-test-db. Proszę, obrzuć mnie swoimi myślami. Wkrótce dodam plik Readme. –

+0

BTW, wyjaśnienie, które ustąpiłeś bardzo precyzyjnie. –

+1

Ten initc może zostać zastąpiony przez TestMain(), jak sądzę. – alexsmn

1

Używam zmiennej globalnej do przechowywania źródła danych (lub ciągów połączeń) bieżącej bazy danych i ustawianej na inną wartość w funkcji testowej. Ponieważ istnieje tylko jedna baza danych, którą muszę obsługiwać, więc wybieram najprostszy sposób.

Powiązane problemy