首頁  >  文章  >  後端開發  >  使用 gorm 和 sqlmock 進行測試

使用 gorm 和 sqlmock 進行測試

王林
王林轉載
2024-02-05 21:39:091127瀏覽

使用 gorm 和 sqlmock 进行测试

問題內容

我正在努力使用 sqlmock 和 gorm 為我的 go lambda 函數編寫測試。

這是我要測試的功能:

func docleanup(con *gorm.db) {
    sixmonthsago := time.now().adddate(0, -6, 0).format("2006-02-01")
    con.where("date_to <= ?", sixmonthsago).delete(&availability{})
    con.where("date_to <= ?", sixmonthsago).delete(&reservation{})
}

這是我的測試:

func testdocleanup(m *testing.t) {
    var mock sqlmock.sqlmock
    var db *sql.db
    var err error

    db, mock, err = sqlmock.new()
    assert.nil(m, err)

    dialector := mysql.new(mysql.config{
        dsn:                       "sqlmock_db_0",
        drivername:                "mysql",
        conn:                      db,
        skipinitializewithversion: true,
    })

    conn, err := gorm.open(dialector, &gorm.config{})
    if err != nil {
        m.errorf("failed to open connection to db: %v", err)
    }

    if conn == nil {
        m.error("failed to open connection to db: conn is nil")
    }

    defer db.close()

    mock.expectquery(fmt.sprintf("delete from availability where date_to <= '%s'", time.now().adddate(0, -6, 0).format("2006-02-01")))
    mock.expectquery(fmt.sprintf("delete from reservations where date_to <= '%s'", time.now().adddate(0, -6, 0).format("2006-02-01")))

    docleanup(conn)

    err = mock.expectationsweremet()
    assert.nil(m, err)

}

我不知道我做錯了什麼。這是我第一次使用 sqlmock。我已經閱讀了一些地方,我的程式碼看起來不錯,但我沒有得到結果。我的錯誤是:

Expected nil, but got: &errors.errorString{s:"there is a remaining expectation which was not matched: ExpectedQuery => expecting Query, QueryContext or QueryRow which:\n  - matches sql: 'DELETE FROM availability WHERE date_to <= '2022-13-06''\n  - is without arguments"}

知道我做錯了什麼嗎?


正確答案


我看到的主要問題在於您期望查詢的方式。而不是

    mock.expectquery(fmt.sprintf("delete from availability where date_to <= '%s'", time.now().adddate(0, -6, 0).format("2006-02-01")))

你應該有:

    mock.expectbegin()
    mock.expectexec("delete from `availability` where date_to <= ?").
        withargs(time.now().adddate(0, -6, 0).format("2006-02-01")).
        willreturnresult(sqlmock.newresult(0, 0))
    mock.expectcommit()

這將告訴模擬您正在使用事務(expectbeginexpectcommit 圍繞刪除),查詢是使用參數進行的(withargs),以及查詢的回傳結果是什麼(willreturnresult

還有一些其他的細微變化,例如表名周圍的``(mysql 習慣用法)和表名(gorm 通常會將名稱複數,因此您要么在availability 上實現 tablename,要么預設為可用性)。

查看所有這些問題的最佳方法是更改​​ docleanup 以傳回錯誤,然後在測試中查看它們:

func docleanup(con *gorm.db) error {
    sixmonthsago := time.now().adddate(0, -6, 0).format("2006-02-01")
    tx := con.where("date_to <= ?", sixmonthsago).delete(&availability{})
    if tx.error != nil {
        return tx.error
    }
    tx = con.where("date_to <= ?", sixmonthsago).delete(&reservation{})
    if tx.error != nil {
        return tx.error
    }
    return nil
}
...
    err = docleanup(conn)
    assert.nil(m, err)
...

這樣做,並使用當前的程式碼,您將得到

Expected nil, but got: &errors.errorString{s:"call to database transaction Begin, was not expected, next expectation is: ExpectedQuery => expecting Query, QueryContext or QueryRow which:\n  - matches sql: 'DELETE FROM availability WHERE date_to <= '2022-13-06''\n  - is without arguments"}

這告訴您 sqlmock 不期望 begin,解決該問題後您將得到本答案第一部分中解決的其他錯誤。

以上是使用 gorm 和 sqlmock 進行測試的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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