Go单测框架
Go Mock
Go Mock 的核心原理就是通过将原始代码中的接口调用替换为 mock 对象,并在测试中对 mock 对象进行合适的设定和断言,从而实现对代码的全面测试。
go get github.com/golang/mock/gomock
go get github.com/golang/mock/mockgen //--可以在写好interface之后把桩代码生成
使用时生成桩代码的命令
//go:generate mockgen -destination=./mock_human.go -source=interface.go
//需要将该行命令写在欲生成桩代码的接口上方(注意等号两边不要有空格) mock_human.go会把该接口实现
运行完上述命令后,会在mock包下生成mock_human实现类
编写mock_human_test.go代码
func Test_mock_human(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockHuman := NewMockHuman(ctrl)
mockHuman.EXPECT().Speak().DoAndReturn(func() string {
return "Hello0000000"
}) //期望的返回结果
outPut := mockHuman.Speak() //调用mock后的方法
t.Errorf("output: %s", output)
}
此外,Go Mock还可以针对方法的调用次数做出个性化设置,最多调用次数,最少调用次数,只能调用次数,调用任意次。
Go Monkey
go monkey相比于go mock来说就十分简单粗暴,go monkey通过直接修改方法的内存空间,实现桩代码替换。这也就意味着,它可以强行给任意方法(面向对象)或函数(面向过程)打桩。
对方法打桩
type Boy struct {
}
func (b *Boy) Speak() string {
return "Hello"
}
func Test_gomonkey(t *testing.T) {
b := Boy{}
patchs := gomonkey.ApplyMethod(reflect.TypeOf(&Boy{}), "Speak", func(b *Boy) string {
return "Bye"
})
defer patchs.Reset()
t.Errorf("Speak: %s", b.Speak())
}
运行结果
gomonkey_test.go:24: Speak: Hello
原本的逻辑被替换
对函数打桩
func Laugh() string {
return "ahahaha"
}
func Test_gomonkey(t *testing.T) {
patch := gomonkey.ApplyFunc(Laugh, func() string {
return "lol"
})
defer patch.Reset()
t.Errorf("Laugh: %s", Laugh())
}
PS: 过于简单的函数go编译器会进行直接内联(inline),所以打桩会失效,因此在执行test时需要关闭内联
go test -v -gcflags=-l gomonkey_test.go