unit-testing - Go Unit test - 在使用 go-sqlmock 模拟 gorm 时,无法将实际 sql 与预期的正则表达式匹配?
问题描述
单元测试时,我使用 sqlmock 模拟 gorm。但是在运行所有初始设置时都很好,但是当实际查询和测试查询匹配时会发生错误。我在下面给出了所有代码。
用户.go
func (r *users) GetUserByID(userID uint) (*domain.User, *errors.RestErr) {
var resp domain.User
res := r.DB.Model(&domain.User{}).Where("id = ?", userID).First(&resp)
if res.RowsAffected == 0 {
logger.Error("error occurred when getting user by user id", res.Error)
return nil, errors.NewNotFoundError(errors.ErrRecordNotFound)
}
return &resp, nil
}
嘲笑
user_test.go
type Suite struct {
suite.Suite
DB *gorm.DB
mock sqlmock.Sqlmock
db *sql.DB
err error
repository repository.IUsers
}
func (s *Suite) SetupSuite() {
s.db, s.mock, s.err = sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherEqual))
require.NoError(s.T(), s.err)
dialector := mysql.New(mysql.Config{
DSN: "sqlmock_db_0",
DriverName: "mysql",
Conn: s.db,
SkipInitializeWithVersion: true,
})
s.DB, s.err = gorm.Open(dialector, &gorm.Config{})
require.NoError(s.T(), s.err)
s.repository = impl.NewMySqlUsersRepository(s.DB)
}
func (s *Suite) AfterTest(_, _ string) {
require.NoError(s.T(), s.mock.ExpectationsWereMet())
}
func TestInit(t *testing.T) {
suite.Run(t, new(Suite))
}
// .................Start Testing....................
func (s *Suite) Test_repository_Get() {
var (
id = uint(1)
user_name = "user-name"
fast_name = "fast-name"
)
s.mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "users" WHERE (id = $1) ORDER BY "users"."id" LIMIT 1`)).
WithArgs(uint(id)).
WillReturnRows(sqlmock.NewRows([]string{"id", "user_name", "fast_name"}).
AddRow(uint(id), user_name, fast_name))
res, _ := s.repository.GetUserByID(uint(id))
require.Nil(s.T(), deep.Equal(&domain.User{ID: uint(id), UserName: user_name, LastName: fast_name}, res))
}
当我执行res, _ := s.repository.GetUserByID(uint(id))
这一行时,它会进入 user.go 文件。在 sql 查询行中出现错误如下所示。
actual sql: "SELECT * FROM `users` WHERE id = ? ORDER BY `users`.`id` LIMIT 1"
does not equal to expected "SELECT \* FROM "users" WHERE \(id = \$1\) ORDER BY "users"\."id" LIMIT 1"
=> expecting Query, QueryContext or QueryRow which:
- matches sql: 'SELECT \* FROM "users" WHERE \(id = \$1\) ORDER BY "users"\."id" LIMIT 1'
- is with arguments:
0 - 1
- should return rows:
row 0 - [1 user-name fast-name]
这里有什么问题?
解决方案
这里的主要问题是sql查询。对于 Get-Item,我们在这里不需要完整的查询。Gorm 会自动生成这个。只需要通过
"SELECT(.*)"
我是从 Medium 上的一篇博文中找到的。 在这里您可以找到详细信息
波纹管代码工作正常
func (s *Suite) Test_repository_GetUserByID() {
var (
id = uint(1)
user_name = "user-name"
first_name = "first-name"
)
s.mock.ExpectQuery("SELECT(.*)").
WithArgs(id).
WillReturnRows(sqlmock.NewRows([]string{"id", "user_name", "first_name"}).
AddRow(uint(id), user_name, first_name))
res, _ := s.repository.GetUserByID(uint(id))
require.Nil(s.T(), deep.Equal(&domain.User{ID: uint(id), UserName: user_name, FirstName: first_name}, res))
}
推荐阅读
- jboss - JBoss 7.2 的 JMS 服务器问题
- reactjs - 如何将数据附加到现有的 json
- ios - 如何在 xcode11 上安装 IOS 12.4.4 模拟器
- mysql - 如何比较两个表中的某个列并将匹配的记录插入到新表中?
- view - 在 Svelte 中,您可以使用 `array = array` 在视图中将数组标记为需要刷新?
- python - 服务器和客户端上的 Python 套接字声明
- android - 在 Android 中实现真正无限捕捉页面的最简单方法是什么?
- tensorflow - 错误:“无法获得卷积算法。” 由 TrackNet
- bash - 简单的 systemd 计时器不会触发
- asp.net - 将 setDate 值传递给控制器操作方法的 enddate 参数后,在 enddate 参数中获取 null 值