英文:
testing gorm with go-sqlmock issue comparing queries with mock.ExpectQuery and 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())
}
这是domain模块的代码:
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 = \?;"
[seccion][1]中存在一个被替换为"SELECT(.*)"的答案,但根据我所读到的,这不是一个真正的解决方案。
[1]: https://stackoverflow.com/questions/68528616/go-unit-test-could-not-match-actual-sql-with-expected-regexp-while-mocking-gor
希望这能帮到你!
英文:
I am having problems comparing the query expected with the true query of gorm, this is my code:
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())
}
here is the module domain:
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"
}
and here the function that I am testing:
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
}
this is the error that I am getting from the console:
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
in this seccion exist an answer that is substitute with "SELECT(.*)" but according to what i had read that is not a real solution
答案1
得分: 1
让我试着帮你找出问题所在。我已经下载了你的所有文件,domain.go
和 repository.go
看起来都没问题。然而,在 repository_test.go
文件中我发现了一些小问题:
- 你编写的 SQL 查询中缺少反引号(backticks)。
- 查询末尾多了一个分号(;)。
- 没有调用
WithArgs(2)
方法。
如果你修复了这些小问题,你的代码应该像下面这样:
// ... 省略部分代码
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())
}
然后,如果你尝试运行测试,应该可以正常工作。如果这解决了你的问题,请告诉我,谢谢!
英文:
Let me try to help to figure out the issue. I downloaded all of your files and the domain.go
and the repository.go
look fine to me.
However, I found some small issues in the repository_test.go
file:
- Backticks missing in the SQL query you wrote
- An extra
;
at the end of the query - The invocation to the method
WithArgs(2)
is missing
If you adjusted these small issues you should have a code that looks like this one:
// ... 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())
}
Then, if you try to run the test it should work.
Let me know if this solves your issue, thanks!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论