首页  >  文章  >  后端开发  >  Gorm 删除子句 sqlmock 测试

Gorm 删除子句 sqlmock 测试

WBOY
WBOY转载
2024-02-08 22:30:31817浏览

Gorm 删除子句 sqlmock 测试

php小编新一为您介绍Gorm删除子句sqlmock测试。Gorm是Go语言中一款优秀的ORM框架,而sqlmock是Gorm的一个测试工具,用于模拟数据库操作。在进行Gorm开发时,我们经常需要进行数据库删除操作的测试,这时候就可以使用sqlmock来模拟数据库的删除操作,以便进行单元测试和集成测试。本文将为您详细介绍如何使用Gorm和sqlmock进行删除子句的测试,帮助您更好地进行数据库相关的开发工作。

问题内容

我有一个 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)

现在带有子句的测试总是失败。例如:

sqlMock.ExpectExec(`DELETE`)
    .WithArgs(expirationDate)
    .WillReturnResult(sqlmock.NewResult(1, 1))

接收错误:

“使用参数 [{name: ordinal:1 value:2023-01-18 06:15:34.694274 +0000 utc}] 调用查询 'delete from "my_users" where created_at a302bd1dc71d5ec9153a69a7b0a157a7 期望 exec 或 execcontext 其中:n - 匹配 sql:'delete'n - 带有参数:n 0 - 2023-01-18 06:15:34.694274 +0000 utc n - 应返回具有以下内容的结果:n lastinsertid: 1n rowsaffected: 1"

我尝试了许多其他 sqlmock 期望,但他们也有类似的问题。 另外,我们在 expectexec 中没有返回值,只有在 expectquery 中... 有人必须用子句测试 gorm 查询吗?

解决方法

我能够成功地管理您的需求。首先,让我分享我编写的文件,然后我将引导您完成所有相关更改。这些文件是用于生产的 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("<a href="https://www.php.cn/link/89fee0513b6668e555959f5dc23238e9" class="__cf_email__" data-cfemail="9febfaecebdffae7fef2eff3fab1fcf0f2">[email&#160;protected]</a>")
    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)
    }
}

这里还有更多值得一提的变化:

  1. 我根据文档实例化了 anytime (您可以在评论中看到链接)。
  2. 我再次猜测了 dbmockgormdb 的设置,但我认为它们应该大致相同。
  3. 我将 expectexec 的用法切换为 expectquery,因为我们将返回 clauses 文件中 expectexec 的用法切换为 expectquery,因为我们将返回 clauses 文件中 repo.go 方法指定的结果集。
  4. 您必须将 expectquery 包装在 expectbeginexpectcommit 中。
  5. 最后,请注意驱动程序对 sql 语句中参数的期望方式的差异。在生产代码中,您可以选择使用?。但在测试代码中,只能使用?,否则不符合预期。

希望能帮上一点忙,否则请告诉我!

以上是Gorm 删除子句 sqlmock 测试的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文转载于:stackoverflow.com。如有侵权,请联系admin@php.cn删除