write testable codes!
當一個團隊合做一個項目時,必然會涉及到接口的調用,這時假若你的上下游團隊成員還未寫好接口,可是又要測試本身的代碼,mock即可派上用場。mock出的對象能模擬接口的行爲,給出預期的結果,好比一個遠程調用接口mock後能夠在本機調用並馬上返回預設的結果。git
1 . go get github.com/golang/mock/
2 . 在/mock/mockgen目錄下執行go build命令生成二進制可執行文件mockgen,並放置PATH環境變量所在目錄下github
0 . 目錄結構:golang
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) }
2 . 在service目錄下執行命令:mockgen -destination ./mocks/service_mock.go -package mocks -source ./service.go
測試
3 . 編寫邏輯層文件/todo/exec.goui
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.gocode
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對象