【问题标题】:How to mock for same input and different return values in a for loop in golang如何在golang的for循环中模拟相同的输入和不同的返回值
【发布时间】:2018-03-04 14:11:35
【问题描述】:

我正在使用 go lang 测试在 for 循环中运行具有多个参数的测试。

我遇到了每次调用模拟时都返回相同的返回值(和第一个集合)的情况。我想要做的是在输入相同时更改每个测试的返回值,即循环中相同的On 但不同的Return

我正在使用stretchr/testify 进行模拟。当On 相同时,它看起来不会覆盖已创建的模拟。

func TestUpdateContactWithNewActions(t *testing.T) {
    tests := []struct {
        testName  string
        getParams func() *activities.UpdateContactWithNewActionsActivity
        mockError error
    }{

        {"UpdateContactWithNewActions with error from contact service",
            func() *activities.UpdateContactWithNewActionsActivity {
                return fixtures.GetUpdateContactWithNewActionsActivity()
            }, fixtures.Err},
        {"UpdateContactWithNewActions valid",
            func() *activities.UpdateContactWithNewActionsActivity {
                return fixtures.GetUpdateContactWithNewActionsActivity()
            }, nil},
    }

    lib.LoadWithMockClients()

    for _, test := range tests {
        test := test
        t.Run(test.testName, func(t *testing.T) {
            lib.MockCSClient.On(
                "UpdateContactWithNewActions",
                mock.AnythingOfType("tchannel.headerCtx"),
                fixtures.UpdateContactWithNewActions).Return(test.mockError)

            returnedResult, err := test.getParams().Execute(fixtures.Ctx)
            if test.mockError == nil {
                // some assertion
            }
            assert.Error(t, err)
        })
    }
}

【问题讨论】:

  • 你使用什么包提供这个On方法?似乎这就是问题所在,而不是 Go 本身。
  • 拉伸/作证
  • 看起来库只是附加到一个内部列表,所以当方法被调用时,它总是匹配注册的第一个返回结果。您是否考虑过为每次测试运行使用新的模拟?
  • 我考虑过,但不要认真尝试,因为MockCSClient 在我的测试中创建的方式。但这是个好主意,我会试试的。
  • 嘿,您找到解决方案了吗?

标签: unit-testing go testify


【解决方案1】:

我也遇到过类似的问题。

解决方法是Once()

在您的模拟中添加一个.Once() 并使用您需要的每个结果重复模拟。

类似这样的:

lib.Mock.On("method", arg).Return(test.mockError).Once()
lib.Mock.On("method", arg).Return(nil).Once()

每个模拟结果只会返回一次。

https://godoc.org/github.com/stretchr/testify/mock#Call.Once

【讨论】:

  • 这是正确的解决方案。如果您正在构建测试用例以验证和强制循环条件或其他内容,您可以使用[]response 并循环通过它为每个响应设置.Once() 的模拟。
  • 谢谢!这个答案必须被接受。
【解决方案2】:

当结果需要只返回一次时,@Marcos 提供的答案效果很好。
但是在每个返回值都需要多次(未知)返回的场景下,就行不通了。

我解决它的方法是直接操作mock.ExpectedCalls。在我的情况下,模拟只包含一个方法,因此只需清理整个 ExpectedCalls 切片很简单,但如果有多个方法,则可以迭代 ExpectedCalls 切片,并仅更新所需的调用。

这是一个简单案例的工作示例:

lib.Mock.On("method", arg).Return("1")

assert.Equal(t, lib.Mock.method(arg), "1")
assert.Equal(t, lib.Mock.method(arg), "1")
....
assert.Equal(t, lib.Mock.method(arg), "1")

lib.Mock.ExpectedCalls = nil // cleanup the previous return value
lib.Mock.On("method", arg).Return("2")
assert.Equal(t, lib.Mock.method(arg), "2")
assert.Equal(t, lib.Mock.method(arg), "2")
....
assert.Equal(t, lib.Mock.method(arg), "2")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多