在开发过程中,使用 go-sqlmock 来测试 gorm 的问题是一种常见的需求。go-sqlmock 是一个用于模拟数据库操作的工具,而 gorm 则是一个流行的 Go 语言 ORM 库。在测试过程中,我们经常需要比较查询语句是否符合预期。为了做到这一点,我们可以使用 mock.ExpectQuery 和 regexp.QuoteMeta 来进行比较。这种方法能够帮助我们更好地测试和调试代码,确保程序的正确性和稳定性。接下来,我们将详细介绍如何使用 go-sqlmock 进行 gorm 测试,并展示如何使用 mock.ExpectQuery 和 regexp.QuoteMeta 进行查询语句的比较。
问题内容
我在比较预期查询与 gorm 的真实查询时遇到问题,这是我的代码:
package repository
import (
"regexp"
"testing"
"github.com/data-dog/go-sqlmock"
"your_go_root/pkg/domain"
"github.com/stretchr/testify/assert"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var successgettransaction domain.transaction = domain.transaction{
id: 2,
buyerid: 2,
sellerid: 5,
itemid: 2,
messageid: 2,
expireddate: "2022-09-010 01:01:00",
createdat: "2022-09-08 01:01:00",
}
func testsuccessgettransactionbyid(t *testing.t) {
db, mock, err := sqlmock.new()
assert.noerror(t, err)
gdb, err := gorm.open(mysql.new(mysql.config{
conn: db,
skipinitializewithversion: true,
}), &gorm.config{})
assert.noerror(t, err)
rows := sqlmock.newrows([]string{"id", "buyer_id", "seller_id", "item_id", "message_id", "expired_date", "created_at"}).
addrow(2, 2, 5, 2, 2, "2022-09-010 01:01:00", "2022-09-08 01:01:00")
mock.expectquery(regexp.quotemeta("select * from transaction where id = ?;")).willreturnrows(rows)
repo := defaultclient(gdb)
actualsectionlist, _ := repo.gettransactionbyid(2)
assert.equal(t, successgettransaction, actualsectionlist, "ambas listas deberian ser iguales")
assert.noerror(t, mock.expectationsweremet())
}
这是模块域:
package domain
type transaction struct {
id int64 `gorm:"primarykey;column:id"`
buyerid int64 `gorm:"column:buyer_id"`
sellerid int64 `gorm:"column:seller_id"`
itemid int `gorm:"column:item_id"`
messageid int `gorm:"column:message_id"`
expireddate string `gorm:"column:expired_date"`
createdat string `gorm:"column:created_at"`
}
func (transaction) tablename() string {
return "transaction"
}
type transactionstatus struct {
id int64 `gorm:"primarykey;column:id"`
transactionid int64 `gorm:"column:transaction_id"`
status int `gorm:"column:status"`
notificationid int `gorm:"column:notification_id"`
createdat string `gorm:"column:created_at"`
}
func (transactionstatus) tablename() string {
return "transaction_status"
}
这是我正在测试的功能:
package repository
import (
"fmt"
"your_go_root/pkg/domain"
"gorm.io/gorm"
)
type repositoryclient interface {
gettransactionbyid(id int) (domain.transaction, error)
}
type repositoryclient struct {
db *gorm.db
}
func defaultclient(db *gorm.db) repositoryclient {
return &repositoryclient{
db: db,
}
}
func (rc repositoryclient) gettransactionbyid(id int) (domain.transaction, error) {
trans := domain.transaction{}
status := rc.db.where("id = ?", id).find(&trans)
if status.error != nil {
return domain.transaction{}, status.error
}
if trans == (domain.transaction{}) {
return domain.transaction{}, fmt.errorf("error finding transaction id %v", id)
}
return trans, nil
}
这是我从控制台收到的错误:
Query: could not match actual sql: "SELECT * FROM `transaction` WHERE id = ?" with expected regexp "SELECT \* FROM transaction WHERE id = \?;"[0m[33m[0.218ms] [34;1m[rows:0][0m SELECT * FROM `transaction` WHERE id = 2
在本节中存在一个用“select(.*)”替代的答案,但根据我读到的内容,这不是真正的解决方案
解决方法
让我尝试帮助解决这个问题。我下载了您的所有文件,并且 domain.go
和 repository.go
对我来说看起来不错。
但是,我在 repository_test.go
文件中发现了一些小问题:
- 您编写的 sql 查询中缺少反引号
- 查询末尾额外的
;
- 缺少对
withargs(2)
方法的调用
如果您调整了这些小问题,您应该得到如下所示的代码:
// ... omitted for brevity
func TestSuccessGetTransactionByID(t *testing.T) {
db, mock, err := sqlmock.New()
assert.NoError(t, err)
gdb, err := gorm.Open(mysql.New(mysql.Config{
Conn: db,
SkipInitializeWithVersion: true,
}), &gorm.Config{})
assert.NoError(t, err)
rows := sqlmock.NewRows([]string{"id", "buyer_id", "seller_id", "item_id", "message_id", "expired_date", "created_at"}).AddRow(2, 2, 5, 2, 2, "2022-09-010 01:01:00", "2022-09-08 01:01:00")
mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM `transaction` WHERE id = ?")).WithArgs(2).WillReturnRows(rows)
repo := DefaultClient(gdb)
actualSectionList, _ := repo.GetTransactionByID(2)
assert.Equal(t, successGetTransaction, actualSectionList, "ambas listas deberian ser iguales")
assert.NoError(t, mock.ExpectationsWereMet())
}
然后,如果您尝试运行测试,它应该可以工作。
如果这解决了您的问题,请告诉我,谢谢!
以上就是使用 go-sqlmock 测试 gorm 问题,将查询与mock.ExpectQuery 和 regexp.QuoteMeta 进行比较的详细内容,更多请关注编程网其它相关文章!