[英]Gorm delete with clauses sqlmock test
I have a Gorm delete with the returning result:我有一个带有返回结果的 Gorm 删除:
expirationDate := time.Now().UTC().Add(-(48 * time.hour))
var deletedUsers Users
res := gormDB.WithContext(ctx).
Table("my_users").
Clauses(clause.Returning{Columns: []clause.Column{{Name: "email"}}}).
Where("created_at < ?", expirationDate).
Delete(&deletedUsers)
Now the test with clauses always fails.现在带有子句的测试总是失败。 eg :例如:
sqlMock.ExpectExec(`DELETE`)
.WithArgs(expirationDate)
.WillReturnResult(sqlmock.NewResult(1, 1))
Receiving error:接收错误:
"call to Query 'DELETE FROM "my_users" WHERE created_at < $1 RETURNING "email"' with args [{Name: Ordinal:1 Value:2023-01-18 06:15:34.694274 +0000 UTC}], was not expected, next expectation is: ExpectedExec => expecting Exec or ExecContext which:\n - matches sql: 'DELETE'\n - is with arguments:\n 0 - 2023-01-18 06:15:34.694274 +0000 UTC\n - should return Result having:\n LastInsertId: 1\n RowsAffected: 1" “使用 args [{Name: Ordinal:1 Value:2023-01-18 06:15:34.694274 +0000 UTC}] 调用查询‘DELETE FROM “my_users” WHERE created_at < $1 RETURNING “email”’,这不是预期的,下一个期望是:ExpectedExec => expecting Exec or ExecContext which:\n - matches sql: 'DELETE'\n - is with arguments:\n 0 - 2023-01-18 06:15:34.694274 +0000 UTC\n - should返回结果有:\n LastInsertId: 1\n RowsAffected: 1"
I tried many other sqlMock expectations, but they have a similar issue.我尝试了许多其他 sqlMock 期望,但它们有类似的问题。 Also, we don't have a return value in ExpectExec, only in ExpectQuery... Any chance someone has to test the Gorm query with the Clauses?此外,我们在 ExpectExec 中没有返回值,只有在 ExpectQuery 中......是否有人必须使用 Clauses 测试 Gorm 查询?
I was able to successfully manage what you need.我能够成功地管理你所需要的。 First, let me share the files I wrote, and then I'll walk you through all of the relevant changes.首先,让我分享我编写的文件,然后我将向您介绍所有相关更改。 The files are repo.go
for production and repo_test.go
for the test code.这些文件是用于生产的repo.go
和用于测试代码的repo_test.go
。
repo.go
package gormdelete
import (
"context"
"time"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Users struct {
Email string
}
func Delete(ctx context.Context, gormDB *gorm.DB) error {
expirationDate := time.Now().UTC().Add(-(48 * time.Hour))
var deletedUsers Users
res := gormDB.WithContext(ctx).Table("my_users").Clauses(clause.Returning{Columns: []clause.Column{{Name: "email"}}}).Where("created_at < ?", expirationDate).Delete(&deletedUsers)
if res.Error != nil {
return res.Error
}
return nil
}
As you didn't provide the full file I tried to guess what was missing.由于您没有提供完整的文件,我试图猜测缺少了什么。
repo_test.go
package gormdelete
import (
"context"
"database/sql/driver"
"testing"
"time"
"github.com/DATA-DOG/go-sqlmock"
"github.com/stretchr/testify/assert"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
// this is taken directly from the docs
// https://github.com/DATA-DOG/go-sqlmock#matching-arguments-like-timetime
type AnyTime struct{}
// Match satisfies sqlmock.Argument interface
func (a AnyTime) Match(v driver.Value) bool {
_, ok := v.(time.Time)
return ok
}
func TestDelete(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error was not expected: %v", err)
}
conn, _ := db.Conn(context.Background())
gormDb, err := gorm.Open(postgres.New(postgres.Config{
Conn: conn,
}))
row := sqlmock.NewRows([]string{"email"}).AddRow("test@example.com")
mock.ExpectBegin()
mock.ExpectQuery("DELETE FROM \"my_users\" WHERE created_at < ?").WithArgs(AnyTime{}).WillReturnRows(row)
mock.ExpectCommit()
err = Delete(context.Background(), gormDb)
assert.Nil(t, err)
if err = mock.ExpectationsWereMet(); err != nil {
t.Errorf("not all expectations were met: %v", err)
}
}
Here, there are more changes that it's worth mentioning:在这里,还有更多值得一提的变化:
AnyTime
as per the documentation (you can see the link in the comment).我根据文档实例化了AnyTime
(您可以在评论中看到链接)。db
, mock
, and gormDb
but I think it should be more or less the same.同样,我猜到了db
、 mock
和gormDb
的设置,但我认为它们应该或多或少是相同的。ExpectExec
to ExpectQuery
as we'll have back a result set as specified by the Clauses
method in your repo.go
file.我将ExpectQuery
ExpectExec
因为我们将返回repo.go
文件中的Clauses
方法指定的结果集。ExpectQuery
within an ExpectBegin
and an ExpectCommit
.您必须将ExpectQuery
包装在ExpectBegin
和ExpectCommit
中。?
在生产代码中,您可以选择使用?
or $1
.或$1
。 However, in the test code, you can only use the ?
但是,在测试代码中,您只能使用?
otherwise it won't match the expectations.否则它将不符合预期。Hope to help a little bit, otherwise, let me know!希望能帮上一点忙,否则,请告诉我!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.