简体   繁体   English

Gorm delete with clauses sqlmock 测试

[英]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:在这里,还有更多值得一提的变化:

  1. I instantiated the AnyTime as per the documentation (you can see the link in the comment).我根据文档实例化了AnyTime (您可以在评论中看到链接)。
  2. Again, I guessed the setup of the db , mock , and gormDb but I think it should be more or less the same.同样,我猜到了dbmockgormDb的设置,但我认为它们应该或多或少是相同的。
  3. I switch the usage of 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方法指定的结果集。
  4. You've to wrap the ExpectQuery within an ExpectBegin and an ExpectCommit .您必须将ExpectQuery包装在ExpectBeginExpectCommit中。
  5. Finally, pay attention to the difference in how the driver expects the parameters in the SQL statement.最后,注意驱动程序期望SQL语句中参数的不同。 In the production code, you can choose to use ?在生产代码中,您可以选择使用? 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM