ArgumentCaptorをスタブに使用する方法は?


161

Mockitoのドキュメントjavadocsではそれは言う

検証ではArgumentCaptorを使用することをお勧めしますが、スタブでは使用しないでください。

しかし、ArgumentCaptorをスタブに使用する方法がわかりません。誰かが上記のステートメントを説明し、ArgumentCaptorをスタブに使用する方法を示したり、それを行う方法を示すリンクを提供したりできますか?


1
スーパーショート&ここに素敵な説明:dzone.com/articles/...
Benj

回答:


271

テストする次のメソッドを想定します。

public boolean doSomething(SomeClass arg);

Mockitoのドキュメントでは、次のようにcaptorを使用しないでください。

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);
assertThat(argumentCaptor.getValue(), equalTo(expected));

スタブ中にマッチャーを使用することができるので:

when(someObject.doSomething(eq(expected))).thenReturn(true);

しかし、検証は別の話です。このメソッドが特定の引数で呼び出されたことをテストで確認する必要ArgumentCaptorがある場合は、これを使用してください。

ArgumentCaptor<SomeClass> argumentCaptor = ArgumentCaptor.forClass(SomeClass.class);
verify(someObject).doSomething(argumentCaptor.capture());
assertThat(argumentCaptor.getValue(), equalTo(expected));

答えてくれてありがとう。質問があります。第3のコードブロックでは、trueの場合にのみ返されることを知っている期待のdoSomethingに渡されます。しかし、2番目のコードブロックでtrueが返されるのはいつですか?または、その場合、someObjectは常にsomeMethodに対してtrueを返しますか?
ません

えっと、「3番目のコードブロックでtrueが返されるのはいつですか?」3番目のコードブロックでは、戻り値を気にせず、デフォルト値にします。ブール値の場合false、そうではありませんtrue
Rorick

いいえ、灰色の背景ブロックをすべてコードブロックとして数えました。最初のワンライナーを含みます。when(someObject.doSomething(argumentCaptor.capture()))。thenReturn(true);
ません

あ、ごめんなさい。はい、この場合、trueは常に返されます。
Rorick

3
「スタブと一緒に使用しない」理由が単純な理由かわからない。マッチャーは実際に期待される引数(タイプのみ)を提供せず、間違っている可能性のある引数にも関わらず、テストに合格することにつながります。
dtc 2016年

0

この線

when(someObject.doSomething(argumentCaptor.capture())).thenReturn(true);

同じことをするだろう

when(someObject.doSomething(Matchers.any())).thenReturn(true);

したがって、スタブに付加価値がないときにargumentCaptor.capture()を使用します。Matchers.any()を使用すると、実際に何が起こるかがわかりやすくなるため、読みやすさが向上します。argumentCaptor.capture()では、実際に一致する引数を読み取ることはできません。そして、any()を使用する代わりに、より多くの情報(期待される引数のクラス)がある場合、より具体的なマッチャーを使用して、テストを改善できます。

また、別の問題:スタブ時にargumentCaptor.capture()を使用すると、検証後に取得する必要がある値の数が不明確になります。まだキャプチャする値がないため、スタブ中ではなく検証中に値をキャプチャします。では、スタブ中に引数キャプターがメソッドをキャプチャするのは何ですか?またはそれは何かをキャプチャしませんか?この質問に対する答えはありません。私はそれを未定義の動作であると考え、未定義の動作を使用したくありません。


0

仮に、検索でこの質問にたどり着いた場合は、おそらく次のようになります。

doReturn(someReturn).when(someObject).doSomething(argThat(argument -> argument.getName().equals("Bob")));

どうして?私のようにあなたは時間を大切.equalsにし、単一のテストシナリオのためだけに実装するつもりはないからです。

また、テストの99%はMockからnullが返されてバラバラになり、合理的な設計nullでは、コストをかけずに戻り、使用OptionalまたはKotlinへの移行を回避します。これverifyは、頻繁に使用する必要がないことを意味し、ArgumentCaptorsはあまりに面倒で書くことができません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.