簡體   English   中英

Gorm delete with clauses sqlmock 測試

[英]Gorm delete with clauses sqlmock test

我有一個帶有返回結果的 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))

接收錯誤:

“使用 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"

我嘗試了許多其他 sqlMock 期望,但它們有類似的問題。 此外,我們在 ExpectExec 中沒有返回值,只有在 ExpectQuery 中......是否有人必須使用 Clauses 測試 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("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)
    }
}

在這里,還有更多值得一提的變化:

  1. 我根據文檔實例化了AnyTime (您可以在評論中看到鏈接)。
  2. 同樣,我猜到了dbmockgormDb的設置,但我認為它們應該或多或少是相同的。
  3. 我將ExpectQuery ExpectExec因為我們將返回repo.go文件中的Clauses方法指定的結果集。
  4. 您必須將ExpectQuery包裝在ExpectBeginExpectCommit中。
  5. 最后,注意驅動程序期望SQL語句中參數的不同。 在生產代碼中,您可以選擇使用? $1 但是,在測試代碼中,您只能使用? 否則它將不符合預期。

希望能幫上一點忙,否則,請告訴我!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM