- 例子
- 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 afterShip
type Repository interface {
Create(key string, value []byte) error
Get(key string) ([]byte, error)
Update(key string, value []byte) error
Delete(key string) error
}
�config 依赖Repository,实现配置文件的增删改查
package afterShip
type 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 afterShip
import (
"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次或多次,默认必须调用一次(仅一次)
// 测试config
res,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)
PASS
ok 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) *Controller
func WithContext(ctx context.Context, t TestReporter) (*Controller, context.Context)