今回は、同一メソッドを呼び出して異なる値を取得する方法についてみていきたいと思います。
Mockitoを使ってテストを行う際、同じメソッド呼び出しに対して異なる戻り値や例外を返す必要がある場合があります。この機能はMockitoの初期バージョンでは存在しませんでしたが、後に追加されました。
なぜこの機能が必要になるのでしょうか? 代表的なユースケースは、イテレーターをモック化する場合です。イテレーターは、呼び出し順に応じて異なる値を返す必要があります。(私の場合は、ループを回しながらrandom.nextInt()をモック化する必要があった)
Mockitoの初期バージョンでは、シンプルなモッキングを推奨するため、この機能は実装されていませんでした。イテレーターの代わりに、Iterableやコレクションをモックするよう推奨されていました。これらならば、実際のコレクションを使ってスタブを作成できるため、自然な方法でモックが可能だったのです。
使い方
しかし、時には連続した呼び出しをスタブする必要があるケースもあります。以下に例を示します。
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
// 1回目の呼び出し: RuntimeExceptionがスロー
mock.someMethod("some arg");
// 2回目の呼び出し: "foo"が出力される
System.out.println(mock.someMethod("some arg"));
// 3回目以降の呼び出し: "foo"が出力される(最後のスタブが優先)
System.out.println(mock.someMethod("some arg"));
連続したスタブ設定をより簡潔に記述する別の方法もあります。
thenReturnはパラメータとして文字列を連続で設定することができ、設定順次に値がモック化できます。
when(mock.someMethod("some arg")).thenReturn("one", "two", "three");
このように、同一メソッド呼び出しに対して異なる戻り値や例外を返す必要がある場合、Mockitoはその機能をサポートしています。イテレーターをモック化するなど、特殊なケースで役立ちます。
終わり
基本的にはシンプルなモッキングが推奨されており、連続スタブは稀なケースでのみ使用することが期待されています。
参考
https://docs.google.com/document/d/15mJ2Qrldx-J14ubTEnBj7nYN2FB8ap7xOn8GRAi24_A/edit
