关于Mock:
write testable codes!
当一个团队合作一个项目时,必然会涉及到接口的调用,这时倘若你的上下游团队成员还未写好接口,但是又要测试自己的代码,mock便可派上用场。mock出的对象能模拟接口的行为,给出预期的结果,比如一个远程调用接口mock后可以在本机调用并立刻返回预设的结果。
环境准备:
1 . go get github.com/golang/mock/
2 . 在/mock/mockgen目录下执行go build命令生成二进制可执行文件mockgen,并放置PATH环境变量所在目录下
示例:
0 . 目录结构:
project
.
└── service
└── mocks
└── service_mock.go
└── service.go
└── todo
└── exec.go
└── exec_test.go
1 . 编写接口文件/service/service.go
package service
type Request struct {
Id int
}
type Reply struct {
Res string
}
type IService interface {
CallTest(req *Request) (*Reply, error)
}
mockgen -destination ./mocks/service_mock.go -package mocks -source ./service.go
- -source:指定接口文件
- -destination:生成的文件名
- -package:生成文件的包名
- -imports:依赖的需要import的包
- -aux_files:接口文件不止一个文件时附加文件
- -build_flags:传递给build工具的参数
3 . 编写逻辑层文件/todo/exec.go
package todo
import (
"fmt"
"project/service"
)
type Client struct {
service.IService
}
func (c *Client) Todo(req *service.Request) error {
reply, err := c.CallTest(req)
if err != nil {
return err
}
fmt.Printf("req_id is %v and reply_res is %v\n:", req.Id, reply.Res)
return nil
}
4.编写测试文件/todo/exec_test.go
package todo
import (
"errors"
"github.com/golang/mock/gomock"
"project/service"
"project/service/mocks"
"testing"
)
func TestTodo(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mock := mocks.NewMockIService(ctrl)
req := &service.Request{Id: 10088}
reply := &service.Reply{Res: "您好,这里是中国行动,充值请按1,其他请挂机~"}
errNil := errors.New("你拨打的电话是空号!")
tests := []struct {
req *service.Request
expectErr error
}{
{req: req, expectErr: nil},
{req: nil, expectErr: errNil},
}
mock.EXPECT().CallTest(req).Return(reply, nil)
mock.EXPECT().CallTest(nil).Return(nil, errNil)
c := &Client{IService: mock}
for i, v := range tests {
err := c.Todo(v.req)
if err != v.expectErr {
t.Errorf("test %v:get wrong expectErr %v and expectErr is %v", i, err, v.expectErr)
}
}
}
5 . 在todo目录下执行go test查看结果
参考链接:https://github.com/golang/mock/blob/master/README.md