有志者,事竟成!如果你在学习Golang,那么本文《模拟sql查询Golang》,就很适合你!文章讲解的知识点主要包括,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~
问题内容我有一个功能:
func (db *dbsqlx) getrefreshtoken(oldtoken string, tx *sqlx.tx) (string, error) {
var refreshtoken string
err := db.templateget(
tx,
&refreshtoken,
`query`,
oldtoken,
)
if err != nil {
return "", errors.wrap(err, "не удалось запросить рефреш токен для указанного токена")
}
return refreshtoken, err
}
如何使用模拟响应为此函数编写测试?
数据库的类型:
type dbsqlx struct {
pgconn *sqlx.db
pgconnctx context.context
}
我尝试编写这段代码。但我不明白如何正确使用该包。
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer db.Close()
mock.ExpectQuery("query").WillReturnRows()
正确答案
您可以使用一些包装器抽象存储和底层数据库句柄(使其可用于纯数据库和交易),然后用另一个存根接口替换它。它甚至不需要在您的代码库中包含额外的库。
您应该记住真实数据库、null 值等潜在的序列化问题,使用 https://github.com/ory/dockertest 添加一些与真实数据的集成测试
但对于简单的情况,包装器就足够了
// root package
type TokenStorage interface {
GetToken(ctx context.Context, oldToken string) (string, error)
}
// yourtestfile_test.go
type TokenStorageStub struct {}
func (t *TokenStorageStub) GetToken(ctx context.Context, oldToken string) (string, error) {
b := make([]byte, 16)
n, err := rand.Read(b)
if n != len(b) || err != nil {
return "", fmt.Errorf("could not successfully read from the system CSPRNG.")
}
return hex.EncodeToString(b), nil
}
// postgres || mysql || sqlite package
// TokenStorage impelements root interface using postgres.
type TokenStorage struct {
db ExtendedDB
}
func NewTokenStorage(db ExtendedDB) (*TokenStorage, error) {
if db == nil {
return nil, errors.New("provided db handle is nil")
}
return &TokenStorage{db: db}, nil
}
func (s *TokenStorage) GetToken(ctx context.Context, oldToken string) (string, error) {
const query = `SELECT ...`
var token string
if err := s.db.QueryRowContext(ctx, query, oldToken).Scan(&token); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, rootpkg.ErrTokenNotFound
}
return nil, fmt.Errorf("postgres: problem while get token using old token: %w", err)
}
return token, nil
}
// Queryer is an interface used for selection queries.
type Queryer interface {
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
}
// Execer is an interface used for executing queries.
type Execer interface {
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
}
// ExtendedDB is a union interface which can query, and exec, with Context.
type ExtendedDB interface {
Queryer
Execer
}
您可以使用 https://github.com/DATA-DOG/go-sqlmock 之类的东西来模拟数据库查询,并对数据库的响应进行各种控制。
尽管应该注意,在测试中模拟数据库查询通常不被认为是良好的测试实践,因为它很可能测试程序的实际实现而不是其行为。
以上就是《模拟sql查询Golang》的详细内容,更多关于的资料请关注编程网公众号!