- 例子
- func
- Call">type Call
- Controller">type Controller
GoMock工具是Golang官方提供的针对接口的代码生成测试工具。在实际的单元测试过程中,通常会选择Mock掉数据库(DB/KV)、外部服务调用操作部分,将这部分功能留在集成测试中完成。
比如我们将数据操作类型抽象成接口Creator、Updater、Deleter等,借助接口的组合功能,针对我们需要的功能进行组合开发。在测试过程中,我们可以借助GoMock工具生成对应的测试辅助代码,再结合testfy使用。
文档:https://pkg.go.dev/github.com/golang/mock
例子
Repository 定义curd接口
package afterShiptype Repository interface {Create(key string, value []byte) errorGet(key string) ([]byte, error)Update(key string, value []byte) errorDelete(key string) error}
�config 依赖Repository,实现配置文件的增删改查
package afterShiptype config struct {db Repository}func newConfig(db Repository) *config {return &config{db: db,}}func (c *config) getConfig(key string) ([]byte, error) {return c.db.Get(key)}func (c *config) updateConfig(key string, value []byte) error {return c.db.Update(key, value)}func (c *config) createConfig(key string, value []byte) error {return c.db.Update(key, value)}func (c *config) deleteConfig(key string) error {return c.db.Delete(key)}
使用gomock 生成Repository 接口的一个测试用实现
mockgen -source=repository.go > repository_mock.go -package afterShip
- -source:指定源文件
- -destination:指定生成代码存放的文件
- -package:指定生成代码的package name
- -imports:指定要导入的包,多个用”,” 隔开
- -self_package:此标志的目的是通过尝试包含自己的包,告诉mockgen要排除哪个导入,防止出现”循环导入”, -self_package xxx
- -copyright_file:版本声明,用于写入文件头
- -write_package_comment:是否生成包注释,用于godoc,默认为true
最后,写测试用例 config_test
package afterShipimport ("github.com/stretchr/testify/assert""testing""github.com/golang/mock/gomock")func TestConfig(t *testing.T) {ctl := gomock.NewController(t)defer ctl.Finish()repository := NewMockRepository(ctl)cfg := newConfig(repository)// 预设值repository.EXPECT().// 不确定入参,可使用 gomock.Any() 作为参数// 确定入参 可使用 gomock.AssignableToTypeOf() 转为该类型参数Get("k1"). // 方法名 与参数Return([]byte("v1"),nil). // 设置返回值AnyTimes() // 允许Get被调用0次或多次,默认必须调用一次(仅一次)// 测试configres,err := cfg.getConfig("k1")assert.Nil(t, err)assert.Equal(t, res,[]byte("v1"))}
执行该用例
mac@weideMacBook-Pro afterShip % go test -v -run TestConfig=== RUN TestConfig--- PASS: TestConfig (0.00s)PASSok commons/afterShip 0.014s
func
// 给定的方法,必须按顺序进行调用func InOrder(calls ...*Call)
type Call
type Call struct {}func (c *Call) AnyTimes() *Call // AnyTimes允许期望被调用0次或更多次func (c *Call) MaxTimes(n int) *Call // 设置最大调用次数func (c *Call) MinTimes(n int) *Call // 设置最小调用次数func (c *Call) Return(rets ...interface{}) *Call // 设置返回值func (c *Call) SetArg(n int, value interface{}) *Call // 设置入参func (c *Call) Times(n int) *Call // 确切的设置方法被调用的次数
type Controller
Controller表示模拟生态系统的顶级控制。它定义了模拟对象的范围和生存期,以及它们的期望。从多个goroutines调用Controller的方法是安全的。每个测试都应该创建一个新的Controller并通过延迟调用Finish。
type Controller struct {T TestHelper}func NewController(t TestReporter) *Controllerfunc WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context)
