我有一个函数:
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
}
字符串
如何用mock response为这个函数编写测试?
DB具有类型:
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()
型
3条答案
按热度按时间xsuvu9jc1#
您可以使用一些 Package 器抽象您的存储和底层数据库句柄(使其对纯数据库和tx有用),然后用另一个存根接口替换它。它甚至不需要在代码库中包含额外的库。
您应该记住真实的数据库、NULL值等潜在的序列化问题,使用https://github.com/ory/dockertest添加一些真实数据的集成测试
但是对于简单的箱子, Package 纸就足够了
字符串
t5fffqht2#
您可以使用类似https://github.com/DATA-DOG/go-sqlmock的东西来模拟数据库查询,并通过数据库对响应进行各种控制。
尽管应该注意,在测试中模拟数据库查询通常不被认为是良好的测试实践,因为它最有可能测试的是程序的实际实现,而不是它的行为。
hmae6n7t3#
这是Golang中大多数现有sql客户端的一个问题,它们并没有真正被创建为可模拟的,所以像我们通常所做的那样编写一个mock(使用一个接口来与它解耦)是行不通的。
为了更清楚地说明为什么使用接口来解耦然后模拟接口不起作用,原因是因为Query和Exec函数返回的结构具有您无法更改的私有属性。
例如,如果你创建一个这样的接口:
字符串
你可以这样写一个mock:
型
但是因为你不能设置
sql.Rows
和sql.Results
的值,所以只能为这两个结构体返回零值,如果你正在编写测试,这几乎不是你所需要的。database/sql最常用的mocking技术
另一种方法是模拟用于连接到数据库的整个驱动程序,这是一个大量工作,利润很少。
幸运的是,这正是在其他答案中提到的https://github.com/DATA-DOG/go-sqlmock库所做的,而且它在这方面做得很好。实际上,这是我所知道的使用现有
sql
库的唯一方法。也许不嘲笑是个更好的主意
在编写测试时模拟数据库请求被广泛认为是一种不好的做法,因为知道SQL代码是否工作的最好/唯一方法是将其发送到数据库的真实的示例并在那里运行它。
因此,模拟它可能会导致您在测试中出现假阳性,然后在生产中出现问题。
如果你想走这条路,有一个有趣的技术使用https://github.com/ory/dockertest,你可以直接从Golang代码在docker容器内启动你的数据库示例,然后在测试结束时停止这台机器。
这为您提供了单元测试的大部分好处,但实际上允许您在真实的的数据库中运行查询。这是我最喜欢的测试数据库的方法。
这里有一个关于postgres的例子,如果有帮助的话,我实际上有一个关于here中每个最大的SQL DBMS的例子。
使用一个库,实际上可以帮助您模拟它
免责声明:我指的是我在这一节中自己编写的一个库
在某些情况下,您可能希望模拟数据库调用,以便可以在较小的更快的测试中测试业务逻辑,然后使用其他较慢的测试来测试实际查询。这种情况并不常见,但我确实为Go写了一个非常好的SQL库,在许多其他东西中,它还提供了一个可以开箱即用的mock,所以这也是一个选择:
https://github.com/vingarcia/ksql的
这里解释了如何使用这个库的内置模拟:
https://github.com/VinGarcia/ksql/wiki/Testing-Tools-and-ksql.Mock的