0%

Go-Test-gomock使用

写出可测试 的代码 至关重要. 可以保证代码的稳定性. 帮助程序员减少bug.

gomock 是一个go官方的模拟框架.
gomock的使用场景:

  • IO类型的数据, 本地文件,数据库,网络API,RPC等
  • 依赖的服务还没有开发好, 这时候可以自己模拟一个服务, 加快开发进度提升开发效率
  • 压力性能测试的时候屏蔽外部依赖, 专注测试本模块
  • 依赖的内部函数非常复杂, 要构造数据非常不方便,这也是一种

gomock

install

go get github.com/golang/mock

go install github.com/golang/mock/mockgen@latest

使用

gomock在许多 开源项目中都有使用. 可以参考一些开源项目。 比如 [gocache](https://github.com/eko/gocache)

使用mockgen 支持两种 自动生成代码的方式.

  1. 指定source,从源文件生成 mock接口

    mockgen -source=./foo.go  -destination=../test/mock/ -pakcage=mock
  2. 通过 reflect 的方式, 这种方式需要传递两种非标志参数来启动. 导入路径 import逗号分隔的需要mock的接口列表

mockgen database/sql/driver  Conn,Driver

mockgen 相关参数

  • -source: 要模拟的接口文件
  • -desitination: mock文件输出的地方,如不设置,默认输出到标准输出中.
  • -package: 生成的 mock 文件的包名, 如不设置则为 mock_ 前缀加上输入的文件名。
  • -imports: 应该在生成的源码文件中显示的导入的包列表. 声明为 foo=bar/baz 形式的并且以逗号分隔的列表. foo表示生成的源码文件中报的标识符, bar/baz 是要导入的包.
  • -aux_files: 应查阅的附加文件列表, 已解决例如在不同文件中定义的嵌入式接口(embbed interface). 声明为 foo=bar/baz.go 形式的并且以逗号分隔的列表. bar/baz.go 是指定的源文件. foo-source 指定的文件的包名.
  • -build_flags: 这个参数只在 reflect模式下使用. 用于 go build 中使用.
  • -mock_names: 自定义生成mock的文件列表. 使用逗号分隔. 例如: Repository=MockSensorRepository,Endpoint=MockSensorEndpoint. Repository Endpoint 是要模拟的接口, MockSensorRepositoryMockSensorEndpoint 是模拟的实现类名. 如果不指定,则使用默认值.

Example

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 方法
ctrl.Finish(): 进行 mock 用例的期望值断言,一般会使用 defer 延迟执行,以防止我们忘记这一操作

官方Demo

参数匹配器

[Matcher](https://github.com/golang/mock/blob/main/gomock/matchers.go#L25) 表示values 的类型. 通常用于表示 mock方法的期望参数.

Matcher接口定义:

// A Matcher is a representation of a class of values.
// It is used to represent the valid or expected arguments to a mocked method.
type Matcher interface {
	// Matches returns whether x is a match.
	Matches(x interface{}) bool

	// String describes what the matcher matches.
	String() string
}

有时,不关心 调用mock时的特定参数,使用 gomock, 可以预期参数 具有固定值(通过 指定预期的 参数值),与谓词匹配, 称为匹配器.

gomock.Any():匹配任何值(任何类型)
gomock.Eq(x):使用反射来匹配是值DeepEqual 到 x
gomock.Nil(): 火柴 nil
gomock.Not(m):(m 匹配器在哪里)匹配匹配器不匹配的值 m, gomock.Not(x)(式中, x 是 不 一个Matcher)匹配的值不 DeepEqual 至 x

需要掌握的

  • 使用 mockgen 生成代码 一节 使用 go:generate 批量生成代码
  • 了解 gomock 是对接口的mock
    • 期望入参
    • 期望返回值
    • 调用次数
    • 调用顺序
    • 执行 Do mock逻辑

参考
gomock 使用
GoMock快速上手教程
Gomock文档

欢迎关注我的其它发布渠道