我能够成功地满足您的需求.首先,让我共享我编写的文件,然后我将向您介绍所有相关的更改.用于生产的文件为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
}
由于你没有提供完整的文件,我试着猜测遗漏了什么.
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)
}
}
在这里,有更多的变化值得一提:
- 我按照文档实例化了
AnyTime
(您可以在注释中看到链接).
- 我再一次猜测了
db
、mock
和gormDb
的设置,但我认为它们应该大致相同.
- 我将
ExpectExec
的用法改为ExpectQuery
,因为我们将得到由您的repo.go
文件中的Clauses
方法指定的结果集.
- 你必须把
ExpectQuery
包在ExpectBegin
和ExpectCommit
里.
- 最后,注意驱动程序期望SQL语句中的参数的不同之处.在产品代码中,您可以 Select 使用
?
或$1
.然而,在测试代码中,您只能使用?
,否则它将不符合预期.
希望能帮上一点忙,不然的话,让我知道!