测试使用go-sqlmock的gorm问题,使用mock.ExpectQuery和regexp.QuoteMeta比较查询。

huangapple go评论129阅读模式
英文:

testing gorm with go-sqlmock issue comparing queries with mock.ExpectQuery and regexp.QuoteMeta

问题

我遇到了一个问题,无法将gorm的查询预期结果与真实查询结果进行比较,以下是我的代码:

  1. package repository
  2. import (
  3. "regexp"
  4. "testing"
  5. "github.com/DATA-DOG/go-sqlmock"
  6. "YOUR_GO_ROOT/pkg/domain"
  7. "github.com/stretchr/testify/assert"
  8. "gorm.io/driver/mysql"
  9. "gorm.io/gorm"
  10. )
  11. var successGetTransaction domain.Transaction = domain.Transaction{
  12. ID: 2,
  13. BuyerID: 2,
  14. SellerID: 5,
  15. ItemID: 2,
  16. MessageID: 2,
  17. ExpiredDate: "2022-09-010 01:01:00",
  18. CreatedAt: "2022-09-08 01:01:00",
  19. }
  20. func TestSuccessGetTransactionByID(t *testing.T) {
  21. db, mock, err := sqlmock.New()
  22. assert.NoError(t, err)
  23. gdb, err := gorm.Open(mysql.New(mysql.Config{
  24. Conn: db,
  25. SkipInitializeWithVersion: true,
  26. }), &gorm.Config{})
  27. assert.NoError(t, err)
  28. rows := sqlmock.NewRows([]string{"id", "buyer_id", "seller_id", "item_id", "message_id", "expired_date", "created_at"}).
  29. AddRow(2, 2, 5, 2, 2, "2022-09-010 01:01:00", "2022-09-08 01:01:00")
  30. mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM transaction WHERE id = ?;")).WillReturnRows(rows)
  31. repo := DefaultClient(gdb)
  32. actualSectionList, _ := repo.GetTransactionByID(2)
  33. assert.Equal(t, successGetTransaction, actualSectionList, "ambas listas deberian ser iguales")
  34. assert.NoError(t, mock.ExpectationsWereMet())
  35. }

这是domain模块的代码:

  1. package domain
  2. type Transaction struct {
  3. ID int64 `gorm:"primaryKey;column:id"`
  4. BuyerID int64 `gorm:"column:buyer_id"`
  5. SellerID int64 `gorm:"column:seller_id"`
  6. ItemID int `gorm:"column:item_id"`
  7. MessageID int `gorm:"column:message_id"`
  8. ExpiredDate string `gorm:"column:expired_date"`
  9. CreatedAt string `gorm:"column:created_at"`
  10. }
  11. func (Transaction) TableName() string {
  12. return "transaction"
  13. }
  14. type TransactionStatus struct {
  15. ID int64 `gorm:"primaryKey;column:id"`
  16. TransactionID int64 `gorm:"column:transaction_id"`
  17. Status int `gorm:"column:status"`
  18. NotificationID int `gorm:"column:notification_id"`
  19. CreatedAt string `gorm:"column:created_at"`
  20. }
  21. func (TransactionStatus) TableName() string {
  22. return "transaction_status"
  23. }

这是我正在测试的函数:

  1. package repository
  2. import (
  3. "fmt"
  4. "YOUR_GO_ROOT/pkg/domain"
  5. "gorm.io/gorm"
  6. )
  7. type RepositoryClient interface {
  8. GetTransactionByID(id int) (domain.Transaction, error)
  9. }
  10. type repositoryClient struct {
  11. db *gorm.DB
  12. }
  13. func DefaultClient(db *gorm.DB) RepositoryClient {
  14. return &repositoryClient{
  15. db: db,
  16. }
  17. }
  18. func (rc repositoryClient) GetTransactionByID(id int) (domain.Transaction, error) {
  19. trans := domain.Transaction{}
  20. status := rc.db.Where("id = ?", id).Find(&trans)
  21. if status.Error != nil {
  22. return domain.Transaction{}, status.Error
  23. }
  24. if trans == (domain.Transaction{}) {
  25. return domain.Transaction{}, fmt.Errorf("error finding transaction id %v", id)
  26. }
  27. return trans, nil
  28. }

这是我从控制台收到的错误信息:

  1. Query: could not match actual sql: "SELECT * FROM `transaction` WHERE id = ?" with expected regexp "SELECT \* FROM transaction WHERE id = \?;"
  2. [seccion][1]中存在一个被替换为"SELECT(.*)"的答案,但根据我所读到的,这不是一个真正的解决方案。
  3. [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:

  1. package repository
  2. import (
  3. "regexp"
  4. "testing"
  5. "github.com/DATA-DOG/go-sqlmock"
  6. "YOUR_GO_ROOT/pkg/domain"
  7. "github.com/stretchr/testify/assert"
  8. "gorm.io/driver/mysql"
  9. "gorm.io/gorm"
  10. )
  11. var successGetTransaction domain.Transaction = domain.Transaction{
  12. ID: 2,
  13. BuyerID: 2,
  14. SellerID: 5,
  15. ItemID: 2,
  16. MessageID: 2,
  17. ExpiredDate: "2022-09-010 01:01:00",
  18. CreatedAt: "2022-09-08 01:01:00",
  19. }
  20. func TestSuccessGetTransactionByID(t *testing.T) {
  21. db, mock, err := sqlmock.New()
  22. assert.NoError(t, err)
  23. gdb, err := gorm.Open(mysql.New(mysql.Config{
  24. Conn: db,
  25. SkipInitializeWithVersion: true,
  26. }), &gorm.Config{})
  27. assert.NoError(t, err)
  28. rows := sqlmock.NewRows([]string{"id", "buyer_id", "seller_id", "item_id", "message_id", "expired_date", "created_at"}).
  29. AddRow(2, 2, 5, 2, 2, "2022-09-010 01:01:00", "2022-09-08 01:01:00")
  30. mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM transaction WHERE id = ?;")).WillReturnRows(rows)
  31. repo := DefaultClient(gdb)
  32. actualSectionList, _ := repo.GetTransactionByID(2)
  33. assert.Equal(t, successGetTransaction, actualSectionList, "ambas listas deberian ser iguales")
  34. assert.NoError(t, mock.ExpectationsWereMet())
  35. }

here is the module domain:

  1. package domain
  2. type Transaction struct {
  3. ID int64 `gorm:"primaryKey;column:id"`
  4. BuyerID int64 `gorm:"column:buyer_id"`
  5. SellerID int64 `gorm:"column:seller_id"`
  6. ItemID int `gorm:"column:item_id"`
  7. MessageID int `gorm:"column:message_id"`
  8. ExpiredDate string `gorm:"column:expired_date"`
  9. CreatedAt string `gorm:"column:created_at"`
  10. }
  11. func (Transaction) TableName() string {
  12. return "transaction"
  13. }
  14. type TransactionStatus struct {
  15. ID int64 `gorm:"primaryKey;column:id"`
  16. TransactionID int64 `gorm:"column:transaction_id"`
  17. Status int `gorm:"column:status"`
  18. NotificationID int `gorm:"column:notification_id"`
  19. CreatedAt string `gorm:"column:created_at"`
  20. }
  21. func (TransactionStatus) TableName() string {
  22. return "transaction_status"
  23. }

and here the function that I am testing:

  1. package repository
  2. import (
  3. "fmt"
  4. "YOUR_GO_ROOT/pkg/domain"
  5. "gorm.io/gorm"
  6. )
  7. type RepositoryClient interface {
  8. GetTransactionByID(id int) (domain.Transaction, error)
  9. }
  10. type repositoryClient struct {
  11. db *gorm.DB
  12. }
  13. func DefaultClient(db *gorm.DB) RepositoryClient {
  14. return &repositoryClient{
  15. db: db,
  16. }
  17. }
  18. func (rc repositoryClient) GetTransactionByID(id int) (domain.Transaction, error) {
  19. trans := domain.Transaction{}
  20. status := rc.db.Where("id = ?", id).Find(&trans)
  21. if status.Error != nil {
  22. return domain.Transaction{}, status.Error
  23. }
  24. if trans == (domain.Transaction{}) {
  25. return domain.Transaction{}, fmt.Errorf("error finding transaction id %v", id)
  26. }
  27. return trans, nil
  28. }

this is the error that I am getting from the console:

  1. 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.gorepository.go 看起来都没问题。然而,在 repository_test.go 文件中我发现了一些小问题:

  1. 你编写的 SQL 查询中缺少反引号(backticks)。
  2. 查询末尾多了一个分号(;)。
  3. 没有调用 WithArgs(2) 方法。

如果你修复了这些小问题,你的代码应该像下面这样:

  1. // ... 省略部分代码
  2. func TestSuccessGetTransactionByID(t *testing.T) {
  3. db, mock, err := sqlmock.New()
  4. assert.NoError(t, err)
  5. gdb, err := gorm.Open(mysql.New(mysql.Config{
  6. Conn: db,
  7. SkipInitializeWithVersion: true,
  8. }), &gorm.Config{})
  9. assert.NoError(t, err)
  10. 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")
  11. mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM `transaction` WHERE id = ?")).WithArgs(2).WillReturnRows(rows)
  12. repo := DefaultClient(gdb)
  13. actualSectionList, _ := repo.GetTransactionByID(2)
  14. assert.Equal(t, successGetTransaction, actualSectionList, "ambas listas deberian ser iguales")
  15. assert.NoError(t, mock.ExpectationsWereMet())
  16. }

然后,如果你尝试运行测试,应该可以正常工作。如果这解决了你的问题,请告诉我,谢谢!

英文:

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:

  1. Backticks missing in the SQL query you wrote
  2. An extra ; at the end of the query
  3. 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:

  1. // ... omitted for brevity
  2. func TestSuccessGetTransactionByID(t *testing.T) {
  3. db, mock, err := sqlmock.New()
  4. assert.NoError(t, err)
  5. gdb, err := gorm.Open(mysql.New(mysql.Config{
  6. Conn: db,
  7. SkipInitializeWithVersion: true,
  8. }), &gorm.Config{})
  9. assert.NoError(t, err)
  10. 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")
  11. mock.ExpectQuery(regexp.QuoteMeta("SELECT * FROM `transaction` WHERE id = ?")).WithArgs(2).WillReturnRows(rows)
  12. repo := DefaultClient(gdb)
  13. actualSectionList, _ := repo.GetTransactionByID(2)
  14. assert.Equal(t, successGetTransaction, actualSectionList, "ambas listas deberian ser iguales")
  15. assert.NoError(t, mock.ExpectationsWereMet())
  16. }

Then, if you try to run the test it should work.
Let me know if this solves your issue, thanks!

huangapple
  • 本文由 发表于 2022年12月16日 02:12:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/74815846.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定