简体   繁体   English

使用 gorm 和 sqlmock 进行测试

[英]Testing with gorm and sqlmock

I am struggling with writing a test for my go lambda function with sqlmock and gorm.我正在努力使用 sqlmock 和 gorm 为我的 go lambda 函数编写测试。

This is the function I want to test:这是我要测试的功能:

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{})
}

And this is my test:这是我的测试:

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)

}

I don't know what I am doing wrong.我不知道我做错了什么。 This is the first time I'm using sqlmock.这是我第一次使用 sqlmock。 I've read up a few places, and my code looks fine, but I'm not getting the results.我已经阅读了一些地方,我的代码看起来不错,但我没有得到结果。 My error is:我的错误是:

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"}

Any ideas what I'm doing wrong?任何想法我做错了什么?

the main problem I see is around the way you are expecting the Query to be.我看到的主要问题是您期望查询的方式。 Instead of代替

    mock.ExpectQuery(fmt.Sprintf("DELETE FROM availability WHERE date_to <= '%s'", time.Now().AddDate(0, -6, 0).Format("2006-02-01")))

you should have:你应该有:

    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()

This will tell the mocking that you are using a transaction ( ExpectBegin and ExpectCommit around the delete, that the query was made with an argument( WithArgs ), and what the return of the query will be ( WillReturnResult )这将告诉模拟您正在使用事务(删除周围的ExpectBeginExpectCommit ,查询是使用参数( WithArgs )进行的,以及查询的返回值是什么( WillReturnResult

There are some other minor changes, like the `` around the table name (a MySQL idiom) and the name of the table (gorm will typically pluralize names so either you implemented TableName on Availability or it will default to availabilities).还有一些其他的小变化,比如表名周围的``(MySQL 惯用语)和表名(gorm 通常会将名称复数化,因此您要么在Availability上实现TableName ,要么默认为可用性)。

The best way for you to see all these problems would be to change the DoCleanup to return errors and then look at them on the test:查看所有这些问题的最佳方法是更改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)
...

Doing this, and with the current code you would get这样做,并使用当前代码你会得到

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"}

This tells you that sqlmock was not expecting a Begin, after solving that you will get the other errors that are resolved in the first part of this answer.这告诉您 sqlmock 不期望开始,在解决之后您将得到本答案第一部分中已解决的其他错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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