Для написания юнит тестов часто требуется «мокать» часть зависимостей, одна из самых распространенных — соединение и операции с базой данных. Если нет возможности использовать внедрение зависимости и использовать интерфейсы типа ExecerContext на входе функции то в дело вступают не совсем чистые хаки в виде Monkey patching.
Патчим открытие соединения sqlx.Connect при помощи библиотеки bou.ke/monkey:
guard = monkey.Patch(sqlx.Connect, func(driverName, dataSourceName string) (*sqlx.DB, error) {
guard.Unpatch()
defer guard.Restore()
db := &sqlx.DB{}
return db, nil
})
Далее патчим defer sqlx.Close:
var dbSQL *sql.DB
guard = monkey.PatchInstanceMethod(reflect.TypeOf(dbSQL), "Close", func(db *sql.DB) error {
guard.Unpatch()
defer guard.Restore()
return nil
})
Ну и при выполнении операций, sqlx.Exec:
guard = monkey.PatchInstanceMethod(reflect.TypeOf(db), "Exec", func(db *sqlx.DB, query string, args ...interface{}) (sql.Result, error) {
guard.Unpatch()
defer guard.Restore()
return nil, nil
})
Теперь мы можем писать тесты на часть кода, которая работает напрямую с базой данных:
...
db, err := sqlx.Connect("postgres", fmt.Sprintf("host=%s port=%s user=%s dbname=%s sslmode=disable password=%s", dbHost, dbPort, dbUser, dbName, dbPass))
if err != nil {
return err
}
defer db.Close()
...
_, err := db.Exec(sql, args...)
if err != nil {
return err
}
...