gomockでmockテストを行う


開発の過程でユニットテストに協力する必要があることが多いが、多くの場合、ユニットテストはデータベース環境に依存し、ネットワーク環境に依存する必要があり、ユニットテストは非常に面倒なことになる.たとえば、Webページを要求し、要求されたデータを処理する必要があります.最初は簡単なhttpサービスを起動してからユニットテストを実行します.しかし、このユニットのテストは非常に重いようです.継続的な統合の過程でも、テストを自動化するために、スクリプトを書いて、対応するサービスを自動的に起動しました.何かを変える必要があるようだ.
mockオブジェクトは上記の問題を解決するために誕生したもので、mock(シミュレーション)オブジェクトは実際の依存オブジェクトの機能をシミュレートすることができ、同時に非常に複雑な準備作業を必要とせず、オブジェクトインタフェースを定義し、それを実現し、テストオブジェクトに渡して使用する必要があります.
go-mockはgo言語のために開発されたmockライブラリで、このライブラリの使用方法は簡単で、自動生成コードをサポートし、得がたい良いツールと言える.go-mockがどのように機能しているかを簡単に説明します.
まず、依存をローカルにダウンロードする必要があります.
go get github.com/golang/mock/gomock
go get github.com/golang/mock/mockgen

1つ目はコード依存で、2つ目はコマンドラインツール(特に使いやすい)です.
gomockがどのように動作しているかを簡単な例で説明します.$GOPATH/srcディレクトリの下にプロジェクトを新規作成しました:hellomock$GOPATH/src/hellomockディレクトリの下にhellomock.goを作成し、インタフェースTalkerを定義しました.
package hellomock

type Talker interface {
    SayHello(word string)(response string)
}

そして私たちはTalker機能を実現した構造体が必要です.もし私たちがこのようなシーンがあるとしたら、私たちは今迎賓の職場を持っていて、迎賓できる迎賓員が必要です.もちろん、この迎賓員は一人でもオウムでもいいです.では、Persion構造体(オウムか何か)を定義し、Talkerインタフェースを実現する必要があります.person.go
package hellomock

import "fmt"

type Person struct{
  name string
}

func NewPerson(name string)*Person{
  return &Person{
      name:name,
  }
}


func (p *Person)SayHello(name string)(word string) {
  return fmt.Sprintf("Hello %s, welcome come to our company, my name is %s",name,p.name)    
}

今、私たちのPersonはすでにTalkerインターフェースを実現しています.今、彼に役割を果たさせましょう.
今、私たちは会社を持っていて、会社には迎賓員がいて、つまり私たちのフロントの女の子がいて、この女の子はTalkerインターフェースを実現しました.彼女は自動的に来客できるSayHello:company.go
package hellomock

type Company struct {
  Usher Talker
}

func NewCompany(t Talker) *Company{
  return &Company{
    Usher:t,
  }
}

func ( c *Company) Meeting(gusetName string)string{
  return c.Usher.SayHello(gusetName)
}

私たちのシーンはすでに設計されていますが、伝統的には、ユニットテストはどのように実現されますか?company_test.go
package hellomock

import "testing"

func TestCompany_Meeting(t *testing.T) {
    person := NewPerson(" ")
    company := NewCompany(person)
    t.Log(company.Meeting(" "))
}

テスト:
/usr/local/go/bin/go test -v hellomock -run ^TestCompany_Meeting$

    company_test.go:8: Hello  , welcome come to our company, my name is  

ok      hellomock    0.013s
を構築するのは簡単ですが、mockオブジェクトでシミュレーションするとmockgenが登場します.
➜  hellomock> mkdir mock                                        
➜  hellomock> mockgen -source=hellomock.go > mock/mock_Talker.go

このとき、mock/mock_Talker.goファイルが生成されます.
自動生成されたファイルは、異なるパッケージの下に同源ファイルがあり、新しいディレクトリを保存する必要があることに注意してください.
ファイルを生成する内容を気にする必要はありません.使用方法を知るだけです.mock_Talker.go
// Automatically generated by MockGen. DO NOT EDIT!
// Source: hellomock.go

package mock_hellomock

import (
    gomock "github.com/golang/mock/gomock"
)

// MockTalker is a mock of Talker interface
type MockTalker struct {
    ctrl     *gomock.Controller
    recorder *MockTalkerMockRecorder
}

// MockTalkerMockRecorder is the mock recorder for MockTalker
type MockTalkerMockRecorder struct {
    mock *MockTalker
}

// NewMockTalker creates a new mock instance
func NewMockTalker(ctrl *gomock.Controller) *MockTalker {
    mock := &MockTalker{ctrl: ctrl}
    mock.recorder = &MockTalkerMockRecorder{mock}
    return mock
}

// EXPECT returns an object that allows the caller to indicate expected use
func (_m *MockTalker) EXPECT() *MockTalkerMockRecorder {
    return _m.recorder
}

// SayHello mocks base method
func (_m *MockTalker) SayHello(name string) string {
    ret := _m.ctrl.Call(_m, "SayHello", name)
    ret0, _ := ret[0].(string)
    return ret0
}

// SayHello indicates an expected call of SayHello
func (_mr *MockTalkerMockRecorder) SayHello(arg0 interface{}) *gomock.Call {
    return _mr.mock.ctrl.RecordCall(_mr.mock, "SayHello", arg0)
}

次に、このmockオブジェクトを使用して、新しいユニットテストを作成する方法を見てみましょう.
func TestCompany_Meeting2(t *testing.T) {
    ctl := gomock.NewController(t)
    mock_talker := mock_hellomock.NewMockTalker(ctl)
    mock_talker.EXPECT().SayHello(gomock.Eq(" ")).Return(" , 。")

    company := NewCompany(mock_talker)
    t.Log(company.Meeting(" "))
    //t.Log(company.Meeting(" "))
}

テスト:
/usr/local/go/bin/go test -v hellomock -run ^TestCompany_Meeting2$
    company_test.go:21:  , 。
ok      hellomock    0.015s

mockオブジェクトで定義した戻り値が返されることがわかります.
なお、mockオブジェクトのSayHelloが許容できるパラメータはgomock.Eq(x interface{})およびgomock.Any()であり、前の要求試験用例の食事はxに厳格に適合し、第2の要求は任意のパラメータの入力を可能にする.たとえば、コメントされたテストで「卵を全部」と入力した結果、エラーが発生し、テストに失敗しました.
/usr/local/go/bin/go test -v hellomock -run ^TestCompany_Meeting2$
    controller.go:113: no matching expected call: *mock_hellomock.MockTalker.SayHello([ ])
exit status 1
FAIL    hellomock    0.007s

本文はレンガを投げて玉を引くこととして、gomockはまだ多くの高級な使い方があって、みんなが自分で探求することができることを望みます.
参考記事:
https://github.com/golang/moc...
https://github.com/grpc/grpc-...
転載は出典を明記してくださいhttp://www.chenquan.me