测试分为4个层次
常犯的错误:
代码 bug 总是在所难免, 越早发现问题解决成本越低, 单测可以尽早的暴露错误。提高代码之路,使得项目更高质量的交付。 起码有三个优点:
引入 gomonkey 有如下好处:
功能列表
函数打桩, 对变量的 mock 实现原理跟 gostub 一样都是通过 reflect 包实现的。除了 mock 变量,gomonkey 还可以直接 mock 导出函数/方法、mock 代码所在包的非导出函数
Go monkey Permission Denied 解决方案:https://github.com/eisenxp/macos-golink-wrapper
mv $GOROOT/pkg/tool/darwin_amd64/link $GOROOT/pkg/tool/darwin_amd64/original_link
cp https://github.com/eisenxp/macos-golink-wrapper/link $GOROOT/pkg/tool/darwin_amd64/link
下载文件,然后再 cp
wget https://raw.githubusercontent.com/eisenxp/macos-golink-wrapper/main/link
gomonkey 提供了如下 mock 方法:
package unittest
import (
"testing"
"github.com/agiledragon/gomonkey"
"github.com/smartystreets/goconvey/convey"
)
var num = 10 //全局变量
func TestApplyGlobalVar(t *testing.T) {
convey.Convey("TestApplyGlobalVar", t, func() {
convey.Convey("change", func() {
patches := gomonkey.ApplyGlobalVar(&num, 150)
defer patches.Reset()
convey.So(num, convey.ShouldEqual, 150)
})
convey.Convey("recover", func() {
convey.So(num, convey.ShouldEqual, 10)
})
})
}
执行结果:
=== RUN TestApplyGlobalVar
..
2 total assertions
--- PASS: TestApplyGlobalVar (0.00s)
PASS
func networkCompute(a, b int) (int, error) {
// do something in remote computer
c := a + b
return c, nil
}
func Compute(a, b int) (int, error) {
sum, err := networkCompute(a, b)
return sum, err
}
func TestFunc(t *testing.T) {
// mock 了 networkCompute(),返回了计算结果2
patches := gomonkey.ApplyFunc(networkCompute, func(a, b int) (int, error) {
return 2, nil
})
defer patches.Reset()
sum, err := Compute(1, 2)
println("expected %v, got %v", 2, sum)
if sum != 2 || err != nil {
t.Errorf("expected %v, got %v", 2, sum)
}
}
结果:
=== RUN TestFunc
expected %v, got %v 2 3
mock_func_test.go:91: expected 2, got 3
--- FAIL: TestFunc (0.00s)
FAIL
可以看到上面的结果,执行时失败的,mock
没有成功。
有时会遇到mock失效的情况,这个问题一般是内联导致的。
为了减少函数调用时的堆栈等开销,对于简短的函数,会在编译时,直接内嵌调用的代码。
我们禁用下内联,然后执行,go test -v -gcflags=-l mock_func_test.go
执行结果:
=== RUN TestFunc
expected %v, got %v 2 2
--- PASS: TestFunc (0.00s)
PASS
对于 go 1.10以下版本,可使用-gcflags=-l禁用内联,对于go 1.10及以上版本,可以使用-gcflags=all=-l。但目前使用下来,都可以。 关于gcflags
的用法,可以使用 go tool compile --help
查看 gcflags
各参数含义
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。