我试图对接收器函数进行单元测试,该函数调用该结构中的其他接收函数。
让我们说我想测试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。
另外,请注意,我不想使用第三方模拟库。
答案 0 :(得分:4)
这是一种非常惯用的方法来测试你的东西。 其他语言可能需要所有这些嘲弄,但是 请不要在Go中这样做。
在您给出的示例中测试代码的自然方式
将是:1)为MyStruct.one
写一个表格驱动的测试
并确保您测试所有情况。现在你知道了one
完美无缺2)对MyStruct.two
做同样的事情。
请注意,测试未导出的内容是可行的,有用的
在Go中很常见。现在不再需要嘲笑了
一些方法,只需3)写一些表驱动测试
MyStruct.Three
并检查它是否有效。
但也许你的方法one
和two
做得更漂亮,而且
访问环境(文件系统,数据库,网络)和
您不希望Three
的测试依赖于此吗?
所以重构你的代码吧!也许Three
不应该是一种方法
MyStruct
但是一个interface OneAndTwoer
的函数
作为参数,您的生产代码使用“真实”调用Three
当您的测试代码使用InMemoryMyStrcuts调用它时,MyStructs
哪些不依赖环境?你可以称之为
mock,我称之为接口的不同实现。
在您的示例中,提供建议很简单:使用表驱动
测试one
,two
和Three
,不要嘲笑。
对于更现实的问题,建议可能会有所不同,但是
如果不知道,很难给出一般性建议
情况。最好的一般建议是:看一下测试
标准库,你几乎可以找到有用的模式
每个测试场景。
答案 1 :(得分:0)
您可以进行重构,以在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
}