【问题标题】:Mocking receiver functions in Go在 Go 中模拟接收器函数
【发布时间】:2015-05-28 13:37:58
【问题描述】:

我正在尝试对调用该结构中其他接收器函数的接收器函数进行单元测试。

假设我想测试 Three() 并在下面模拟对 two() 的调用:

type MyStruct struct {
    a string
    b string
}

func (m *MyStruct) one() int {
    return 2
}

func (m *MyStruct) two() int {
    return m.one() * 2
}

func (m *MyStruct) Three() int {
    return m.two() * 2
}

我正在遵循以下answer的方法二。

我为每个想要进行单元测试的函数创建了一个自定义构造函数,并用模拟版本覆盖了这些方法。但我想,一旦函数数量增加,代码维护可能并不容易。

是否有任何首选方法来模拟此类函数?我希望官方文档有一些关于如何在不同场景中模拟事物的指南,类似于 Python 上的 mox 提供的。

另外,请注意,我不想使用第三方模拟库。

【问题讨论】:

  • 何必呢?我认为每个方法的单元测试绰绰有余。将方法“三”的单元测试想象成一个迷你集成测试。
  • 这正是我想要做的。我想模拟所有这些调用,因为我只测试特定函数的功能。功能“三”可以是这里的任何功能。它不一定是综合测试。
  • 为什么我不想使用第三方模拟库unittest.mock 在 python3.2 之前一直是第三方库,在 python2.7 中,您需要始终通过 pip 安装它。
  • 这是另一种带有完整示例的方法,应该清楚地说明如何在 Go 中编写可测试的代码:stackoverflow.com/a/48206430/828366
  • Mock functions in Go的可能重复

标签: unit-testing go mocking


【解决方案1】:

这是测试你的东西的一种非常不习惯的方式。 在其他语言中可能需要所有这些嘲笑,但是 请不要在 Go 中这样做。

在您提供的示例中测试代码的自然方法 将是: 1) 为MyStruct.one 编写一个表驱动测试 并确保您测试所有案例。现在你知道one 工作得很好 2) 对MyStruct.two 做同样的事情。 请注意,测试未导出的东西是可能的、有用的并且 在 Go 中很常见。现在不再需要模拟 一些方法,只需 3) 编写一些表驱动测试 MyStruct.Three 并检查它是否有效。

但也许你的方法 onetwo 可以做一些更有趣的事情,并且 访问环境(文件系统、数据库、网络)和 您不希望您对Three 的测试依赖于此吗? 所以重构你的代码!也许Three 不应该是一种方法 MyStruct 的一个函数,它采用 interface OneAndTwoer 作为参数,您的生产代码使用“real”调用Three MyStructs,而您的测试代码使用 InMemoryMyStrcuts 调用它 哪些不依赖环境?你可以称之为 mock,我称之为接口的不同实现。

在您的示例中,提供建议很简单:使用表驱动 测试 onetwoThree 并且不要模拟。 对于更现实的问题,建议可能会有所不同,但 在不知道的情况下很难给出一般性的建议 情况。最好的一般建议是:看看 标准库,您可以在其中找到几乎适用于 每个测试场景。

【讨论】:

  • 假设one 在这种情况下进行网络调用,你如何为two 编写测试?
  • @Siddhart 使用 net/http/httptest.Server 设置测试服务器,并让one 进行“网络调用”。我知道:有些学校教“单元测试 == 不访问任何东西,没有文件系统,没有数据库,没有网络,什么都没有”。这是学术界的混蛋,因此很好。在现实生活中:在没有可用文件系统或无法调用本地 HTTP 服务器的系统上,您多久运行一次单元测试?
【解决方案2】:

您可以进行重构以将两个作为函数传递给Three,这样您就可以直接模拟输入。

func main() {
    var ms MyStruct
    fmt.Println(ms.one())
    fmt.Println(ms.two())
    fmt.Println(ms.Three(ms.two))
}

type MyStruct struct {}

func (m *MyStruct) one() int {
    return 2
}

func (m *MyStruct) two() int {
    return m.one() * 2
}

func (m *MyStruct) Three(two func() int) int {
    return two() * 2
}

【讨论】:

    猜你喜欢
    • 2013-10-10
    • 1970-01-01
    • 2010-12-30
    • 2016-05-08
    • 2021-12-24
    • 1970-01-01
    • 2022-10-15
    • 2017-07-30
    • 1970-01-01
    相关资源
    最近更新 更多