Closed7
Goのモックライブラリの技術選定
※ざっと簡単に試しただけなので間違いあるかもです
一番有名であろうgomockを使っていたけれど、使いにくいなーってことが多いのでその他の選択肢を探る。
候補
実験用
個人的にモックライブラリにほしいもの。どれもJUnit + Mockitoでやってた頃の感覚に近くしたいためにほしい
- interface以外もモック化可能
- mockの振る舞い定義しなくてもスタブとして利用可能
- リフレクションでテストコード内だけで完結
- 記述量少なめ
- privateメソッドでプリセットのモックをいい感じにまとめやすい。テストコードのリファクタリングがやりやすい
- モックへの入力値の検査可能
GoMock
サンプル: https://github.com/abekoh/go-mock-libs/blob/main/application/app_gomock_test.go
- Stars: 7.1k 一番有名
-
mockgen
コマンドでモック生成 -
EXPECT()
で振る舞いを定義- 定義すると呼び出しがないと怒られる、
AnyTimes()
をつければ解決
- 定義すると呼び出しがないと怒られる、
- スタブらしくゼロ値をそのまま返すだけ、にも振る舞い定義する必要あり
- Contrllerを使ってセットアップ&お片付けする必要あり
- 引数チェックMatcherのデフォルト実装が自由度が低め。 こちら とか参考に自由度高いMatcher用意すると良さげ
- 生成される引数、戻り値など
interface{}
だったりで元のコードとにらめっこする必要ある
mockery (testify)
サンプル: https://github.com/abekoh/go-mock-libs/blob/main/application/app_mockery_test.go
- Start: 3.5k
- 実体は stretchr/testify/mock で、それをCLIで簡単に実装できるようにしたやつ
-
mockery --all --keeptree
と実行してみて go:generate 書かなくてもinterface全部のmock作ってくれた - 引数のチェックも
mock.MatchedBy
で簡単に実装できる - スタブ実装も振る舞い定義する必要あり
- CLI機能豊富でいろいろできそう
- GoMock同様
interface{}
多様、メソッド名もstringで指定なので元の実装にらめっこ必要
Moq
サンプル: https://github.com/abekoh/go-mock-libs/blob/main/application/app_moq_test.go
- Stars: 1.3k
- GoMockに似たコード生成
- モックのフィールド値としてfunctionを持つものを生成し、それを書き換えることで振る舞い変える。シンプルながらよい
- 引数チェックはfunctionの中に
t.Errorf()
入れたりassert.Equal()
入れたりでよしなにできそう - timesとか無いが、
XXXCalls()
で呼び出した引数あとから呼べるので、そこで呼び出し回数チェックできる。ここでもassert.Equal()
とかよしなに使える - interfaceと同じ階層であれば特に問題ないが、完全に別のディレクトリに置こうとすると動かない、同じpackageである必要あるっぽい
- 引数、戻り値など
interface{}
ではなくそのままの型なので型安全に実装できる - オプションでゼロ値を返すだけのスタブをデフォルトにできる
- デフォルトのモックをprivate methodでまとめて定義→テストごとに必要なら上書き、といったことが簡単にできそう
所感
Moqがとてもよかった。Starsは少なめだが最近もメンテされている。
シンプルな実装であるがゆえ、柔軟にアサーションできてりテストコードリファクタリングができそう。
実務でも試してみることにする。
このスクラップは2022/10/15にクローズされました