【问题标题】:Mock function without receiver没有接收器的模拟功能
【发布时间】:2020-06-05 04:43:13
【问题描述】:

我有文件util.go:

func Foo(service *SomeService) error {
    return helper(service)
}

func helper(service *SomeService) error {
    ...
}

我正在使用testify 编写单元测试,从Foo 开始。我想:

  1. 模拟helper
  2. assert mocked helper 被调用了 1 次

我在https://stackoverflow.com/a/19168875/1661745 看到了一些有前途的解决方案,但不确定:

方法一:将helper作为Foo的参数传递。我的疑问:testify 需要一个 Mock 结构来 AssertNumberOfCalls,而这里没有结构。

方法二:为Foo创建一个结构体。我的疑问:我不知道为 utils 创建一个结构是否有意义。还需要更多的重构,因为Foo 的调用者需要一个 utils 结构。

最好的方法是什么?

【问题讨论】:

  • 你根本不应该嘲笑。编写适当的测试。如果helper 没有副作用,则无需检查它是否只被调用过一次。如果它有副作用:测试它们是否以预期的方式发生。看看标准库是如何进行测试的。
  • helper 确实有副作用(呼叫服务/数据库)。我来自 Java 世界,那里的依赖项将被模拟以进行单元测试。我不想设置这些依赖项。
  • 在对Foo进行单元测试时,我想模拟helper,因为我计划对helper进行单独的单元测试。
  • Go 中的正确单元测试不像 Java 中的单元测试那样完成。为助手编写测试并为 Foo 编写测试,但除非您的 foo 测试需要调用不同的助手(在您的情况下没有副作用):不要模拟它。真的。别这样。它可能(也可能不是)在 Java 中是正确的测试方式,但在 Go 中却不是正确的做法。
  • 正如@Volker 所说,您不需要模拟助手。您可以为助手编写测试。如果助手通过了测试,那么 Foo 也会。

标签: go testify go-testing


【解决方案1】:

如果您只是想测试在helper 中调用的参数,这是我一直在使用的一种方法。同样的测试也将证明你的助手只被调用了一次。

    // Code

    var originalFn = func(arg1, arg2 string) {
        ...
    }


    func Foo() {
        originalFn(arg1,arg2)
    }

    // Tests

    func TestFoo(t *testing.T) {
        tempFn := originalFn
        var fnArgs []string
        originalFn = func(arg1, arg2) {
            fnArgs = append(fnArgs, []string{arg1, arg2})
        }
        defer originalFn = tempFn

        tests := []struct{
            expected []string
        }{
            {
                expected: []string{"arg1", "arg2"},
            },
        }

        for _, tt:= range tests {
            fnArgs := make([]string, 0)
            Foo()
            assert.Equal(t, tt.expected, fnArgs)
        }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 2020-07-06
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多