互联网三网合一网站建设二十条优化措施
GitHub - bytedance/mockey: a simple and easy-to-use golang mock library
Go mockito 是什么?
mockey是一个简单易用的golang mock库,可以快速方便的mock函数和变量。目前广泛应用于字节跳动服务的单元测试编写。底层是monkey patch,通过在运行时重写函数指令实现。
- 编译时需要关闭inlining和compilation optimization,否则mock可能失败或者报错。有关详细信息,请参阅以下常见问题解答章节。
- 在实际编写单元测试的过程中,推荐配合Convey库一起使用。
安装
go get github.com/bytedance/mockey@latest
快速指南
import ("fmt""testing". "github.com/bytedance/mockey". "github.com/smartystreets/goconvey/convey"
)func Foo(in string) string {return in
}type A struct{}func (a A) Foo(in string) string { return in }var Bar = 0func TestMockXXX(t *testing.T) {PatchConvey("TestMockXXX", t, func() {Mock(Foo).Return("c").Build() // mock functionMock(A.Foo).Return("c").Build() // mock methodMockValue(&Bar).To(1) // mock variableSo(Foo("a"), ShouldEqual, "c") // assert `Foo` is mockedSo(new(A).Foo("b"), ShouldEqual, "c") // assert `A.Foo` is mockedSo(Bar, ShouldEqual, 1) // assert `Bar` is mocked})// mock is released automatically outside `PatchConvey`fmt.Println(Foo("a")) // afmt.Println(new(A).Foo("b")) // bfmt.Println(Bar) // 0
}
特征
对象 | 分类 | 功能细节 |
函数 | 基础 mock | 普通函数 |
可变参数函数 | ||
普通方法 | ||
可变参数方法 | ||
嵌套结构体方法 | ||
私有类型的导出方法(不同包下) | ||
其他功能 | mock 后执行原函数 | |
goroutine 条件过滤 | ||
增量改变 mock 行为 | ||
获取原函数执行次数 | ||
获取 mock 函数执行次数 | ||
变量 | 基础 mock | 普通变量 |
函数变量 |
兼容性
OS Support
- Mac OS(Darwin)
- Linux
- Windows
Arch Support
- AMD64
- ARM64
Version Support
- Go 1.13+
License
Mockey is distributed under the Apache License, version 2.0. The licenses of third party dependencies of Mockey are explained here.
FAQ
如何禁用内联和编译优化?
- Command line:
go test -gcflags="all=-l -N" -v ./...
- Goland:fill
-gcflags="all=-l -N"
in the Run/Debug Configurations > Go tool arguments dialog box
mock后还是进入了原来的函数?
- 尝试使用调试模式。如果能跑通,说明就是问题所在。
- 忘记调用了
Build()
,导致没有实际效果 - 目标函数不完全匹配:
func TestXXX(t *testing.T) {Mock((*A).Foo).Return("c").Build()fmt.Println(A{}.Foo("a")) // enters the original function, because the mock target should be `A.Foo`a := A{}Mock(a.Foo).Return("c").Build()fmt.Println(a.Foo("a")) // enters the original function, because the mock target should be `A.Foo` or extracted from instance `a` using `GetMethod` }
- 目标函数在其他goroutines中执行:
func TestXXX(t *testing.T) {PatchConvey("TestXXX", t, func() {Mock(Foo).Return("c").Build()go Foo("a") // the timing of executing 'foo' is uncertain})// when the main goroutine comes here, the relevant mock has been released by 'PatchConvey'. If 'foo' is executed before this, the mock succeeds, otherwise it failsfmt.Println("over")time.Sleep(time.Second) }
报错“功能太短无法打补丁”?
- 内联或编译优化未禁用:您可以尝试使用调试模式。如果能跑通,说明就是问题所在。请转到常见问题解答的相关部分
- 函数真的太短了:意思是目标函数不到一行,导致编译出来的机器码太短。一般两行以上不会出现这个问题
PatchConvey
Repeat mocking the same function:以最小单位重复mock同一个函数。如果有这样的需求,请获取Mocker
实例并重新mock。- 其他工具mock这个函数:比如monkey或者其他工具mock过这个函数