首頁  >  文章  >  後端開發  >  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 2da6999b461182d1f38aeb3588595a72 期望exec 或execcontext 其中:\n - 匹配sql:'delete'\n - 帶有參數:\n 0 - 2023-01-18 06:15:34.694274 0000 utc\ n - 應傳回具有以下內容的結果:\n lastinsertid: 1\n 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 檔案中repo.go 方法指定的結果集。
  4. 您必須將 expectquery 包裝在 expectbeginexpectcommit 中。
  5. 最後,請注意驅動程式對 sql 語句中參數的期望方式的差異。在生產程式碼中,您可以選擇使用?$1。但在測試程式碼中,只能使用?,否則不符合預期。

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

以上是Gorm 刪除子句 sqlmock 測試的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除