关于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