Go言語の mockgen と go generate で簡単に mock を作成する方法

go generate でパッケージ名とファイル名を利用する


Posted on Sun, Jan 6, 2019
Tags golang, mock

Go言語の mockgen で簡単に mock を揃える方法

Go 言語では go generate というプログラムコードを生成するための仕組みがあります。

Generating code - The Go Blog

いきなり、チューリング完全について出てきて、は? となりますが、言いたいことは、yacc や protocol buffer, go test でも、コードを解釈してコードを生成することがプログラミング言語において重要になるということのようです。 (Make でもできますが、Go言語としてインテグレーションされているのが大切だということなのでしょう)

go generate については、すでに様々な記事があるので、DRY するとして、

ポイントとしては、「コードを生成してくれる Go 標準の枠組み」ということです。

mockgen をまだ打っているの?

Go言語の標準の mockgen を利用するとき、多くの人は下記のコマンドを実行していると思います。

mockgen -source program.go -destination mock_program.go

しかし、「コードを生成してくれる Go 標準の枠組み」 である go generate を利用すると、

//go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAGE
package fitbitauth

// Factory : Creates objects in this package
type Factory interface {
	FileStore() (Store, error)
	FitbitAuthHandler(fap *FitbitAuthParams, ftp *FitbitTokenParams) FitbitAuthHandler
}

Go-zen-chu/gae-fitbit-go/pkg/domain/fitbit.go

と一行目に go:generate の記述をして、あとは、go generate するだけで、mock を作成してくれます。

このとき、$GOFILE でこのファイルの名前を利用し、$GOPACKAGE でパッケージ名を利用することで、同一パッケージ、mock_ファイル名のモックを作成できます。

すると、gae-fitbit-go/pkg/domain/fitbitauth のように、mock ファイルを同一フォルダに生成できるので、大変便利です。

make ファイルで mockgen をされていた方は、ぜひ利用してみてください。

(2019/07/29 更新)go mod を利用したリポジトリで mockgen をしたら、source の package も import されてしまう

go mod により GOPATH/src/github.com/… で開発する必要が必ずしもなくなったのですが、その影響で mockgen が自身のパッケージを認識でない問題が発生しました。

mockgen source mode does not work with go1.11 modules · Issue #230 · golang/mock

self_package というオプションに、自身の GOPACKAGE を記述することにより、その package の import を封じることができます。

//go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAGE -self_package=github.com/go-zen-chu/pkg/domain/$GOPACKAGE 
package fitbitauth

これまで全く mockgen コマンドを実行すればよかったのに、これだと辛いですね…