https://github.com/golang/mock
go install github.com/golang/mock/mockgen@v1.5.0
Source mode
Source mode generates mock interfaces from a source file. It is enabled by using the -source flag.
mockgen -source=foo.go
Reflect mode
Reflect mode generates mock interfaces by building a program that uses reflection to understand interfaces. It is enabled by passing two non-flag arguments: an import path, and a comma-separated list of symbols.
mockgen database/sql/driver Conn,Driver
go:generate
.mockgen . Conn,Driver
用法
在 mockgen 命令中,支持两种生成模式:
1、 source:从源文件生成 mock 接口(通过 -source 启用)
mockgen -source=foo.go [other options]
2、 reflect:通过使用反射程序来生成 mock 接口。它通过传递两个非标志参数来启用:导入路径和逗号分隔的接口列表
mockgen database/sql/driver Conn,Driver
从本质上来讲,两种方式生成的 mock 代码并没有什么区别。
步骤
想清楚整体逻辑
定义想要(模拟)依赖项的 interface(接口)
使用 mockgen 命令对所需 mock 的 interface 生成 mock 文件
编写单元测试的逻辑,在测试中使用 mock
进行单元测试的验证
执行以下命令
$ mockgen -source=./person/male.go -destination=./mock/male_mock.go -package=mock
在执行完毕后,可以发现 mock/ 目录下多出了 male_mock.go 文件,这就是 mock 文件。那么命令中的指令又分别有什么用呢?如下:
-source:设置需要模拟(mock)的接口文件
-destination:设置 mock 文件输出的地方,若不设置则打印到标准输出中
-package:设置 mock 文件的包名,若不设置则为 mock_ 前缀加上文件名(如本文的包名会为 mock_person)
gomock.NewController:返回 gomock.Controller,它代表 mock 生态系统中的顶级控件。定义了 mock 对象的范围、生命周期和期待值。另外它在多个 goroutine 中是安全的
mock.NewMockMale:创建一个新的 mock 实例
gomock.InOrder:声明给定的调用应按顺序进行(是对 gomock.After 的二次封装)
mockMale.EXPECT().Get(id).Return(nil):这里有三个步骤,EXPECT()返回一个允许调用者设置期望和返回值的对象。Get(id) 是设置入参并调用 mock 实例中的方法。Return(nil) 是设置先前调用的方法出参。简单来说,就是设置入参并调用,最后设置返回值
NewUser(mockMale):创建 User 实例,值得注意的是,在这里注入了 mock 对象,因此实际在随后的 user.GetUserInfo(id) 调用(入参:id 为 1)中。它调用的是我们事先模拟好的 mock 方法
ctl.Finish():进行 mock 用例的期望值断言,一般会使用 defer 延迟执行,以防止我们忘记这一操作
https://segmentfault.com/a/1190000017132133
https://www.jianshu.com/p/598a11bbdafb
https://www.cnblogs.com/li-peng/p/13345307.html
https://blog.csdn.net/ayqy42602/article/details/108144457
https://blog.codecentric.de/2019/07/gomock-vs-testify/
https://github.com/gravityblast/fresh