微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

一个 Go 测试用例中的 DB Mocking 会干扰其他测试用例

如何解决一个 Go 测试用例中的 DB Mocking 会干扰其他测试用例

我有两个 Go 测试用例,如下所示,用于测试名为 MyEndpoint 的 gRPC 函数

MyEndpoint 应该在它选择的数据库行具有 Field1 == "A" 时成功,否则返回错误

我正在用 go-sqlmock package from Data-dog 模拟数据库

package mypackage_test

import (
    "github.com/DATA-DOG/go-sqlmock"
    "github.com/stretchr/testify/require"
)


type MyEntity struct {
    Id                     sql.NullInt32 `db:"id"`  
    Field1                 sql.NullString `db:"field1"`
    Field2                 sql.NullString `db:"field2"`
    Field3                 sql.NullString `db:"field3"`
}

var Columns = []string{
    "id","field_1","field_2","field_3"
}



var dbrow = []driver.Value{int32(999),"A","B","C"]


func TestMyTestA(t *testing.T) {
    t.Run("Verify MyEndpoint Fails when mocked Database row has Field1 != A",func(t *testing.T) {
        api,err := getMyAPI()
        require.Nil(t,err)
        defer api.Close()

        api.DBMock.ExpectBegin()
        api.DBMock.MatchExpectationsInorder(false)

        modifiedDbrow := dbrow
        modifiedDbrow[0] = "Z"
        api.DBMock.ExpectQuery("SELECT").
            WithArgs(int32(999)).WillReturnRows(sqlmock.NewRows(Columns).AddRow(modifiedDbrow...))
        api.DBMock.ExpectCommit()
        
        _,err = ... // Call MyEndpoint with parameter Id: int32(999)
        api.DBMock.ExpectClose()
        require.NotNil(t,err)
    })
}

func TestMyTestB(t *testing.T) {
    t.Run("Verify MyEndpoint succeeds when mocked Database row has Field1 == A",err)
        defer api.Close()

        api.DBMock.ExpectBegin()
        api.DBMock.MatchExpectationsInorder(false)

        api.DBMock.ExpectQuery("SELECT").
            WithArgs(int32(999)).WillReturnRows(sqlmock.NewRows(Columns).AddRow(dbrow...))
        api.DBMock.ExpectCommit()
        
        _,err = ... // Call MyEndpoint with parameter Id: int32(999)
        api.DBMock.ExpectClose()
        require.Nil(t,err)
    })
}

当我单独运行这两个测试用例时,它们都通过了。

但是当我一起运行它们时,TestMyTestB 会失败,因为它认为 Field1 == "Z"。 很明显,TestMyTestA 正在干扰 TestMyTestB。为什么?

似乎在 TestMyTestA 情况下完成的模拟在到达 TestMyTestB 时仍然有效,而我在 TestMyTestB 情况下所做的模拟完全被忽略。

如何相互独立地模拟这两个测试用例?

解决方法

这是因为在您的第一次测试中对 modifiedDBRow 切片的分配不正确。请记住,切片不存储任何数据,它只是描述底层数组的一部分。

因此,当您在第一个测试中修改 modifiedDBRow 时,您已经本质上修改了包含 [0] 处的值的基础数组,从 AZ,当您在下一次测试中阅读了 dbRow。要么在第一次测试结束时重置该值,要么使用一组不同的变量来跨测试使用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。