Для написания юнит тестов часто требуется «мокать» часть зависимостей, одна из самых распространенных — соединение и операции с базой данных. Если нет возможности использовать внедрение зависимости и использовать интерфейсы типа 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 } ...