Mockito ArgumentMatchers
1.概要
このチュートリアルは
ArgumentMatcher
_の使い方と
ArgumentCaptor_
との違いを示します。
Mockitoフレームワークの紹介については、
この記事へ
を参照してください。
2. Mavenの依存関係
単一の成果物を追加する必要があります。
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.21.0</version>
<scope>test</scope>
</dependency>
Mockito
の最新バージョンが見つかります。
Maven Central
で。
3.
ArgumentMatchers
モックメソッドをさまざまな方法で設定することが可能です。そのうちの1つは固定値を返すことです。
doReturn("Flower").when(flowerService).analyze("poppy");
上記の例では、
String
“ Flower”は分析サービスが
String
“ poppy”を受信した場合にのみ返されます。
しかし、
もっと広い範囲の値や、事前に未知の値に対応する必要があるかもしれません
これらのすべてのシナリオで、
argument
__
matchers
でモックメソッドを設定できます。
when(flowerService.analyze(anyString())).thenReturn("Flower");
さて、
anyString
引数マッチャーのために、どんな値を分析に渡しても結果は同じになります。
ArgumentMatchers
を使用すると、柔軟な検証またはスタブ作成が可能になります。
メソッドに複数の引数がある場合、** 引数の一部だけに
ArgumentMatchers
を使用することはできません。
Mockito
では、すべての引数を
matchers
または正確な値で指定する必要があります。
次の例は、これに対する誤ったアプローチです。
abstract class FlowerService {
public abstract boolean isABigFlower(String name, int petals);
}
FlowerService mock = mock(FlowerService.class);
when(mock.isABigFlower("poppy", anyInt())).thenReturn(true);
それを修正して
String
の名前を望みどおりに「ポピー」にするには、
eq matcher
を使用します。
when(mock.isABigFlower(eq("poppy"), anyInt())).thenReturn(true);
__matcher
__が使われるときに注意するべきもう2つのポイントがあります:
-
これらを戻り値として使用することはできません
。
スタブコール
最後に、
検証の外では
matchers
引数を使用できません
スタブ**
最後のケースでは、
Mockito
は見当違いの引数を検出し、
InvalidUseOfMatchersException
をスローします。
悪い例は次のようになります。
String orMatcher = or(eq("poppy"), endsWith("y"));
verify(mock).analyze(orMatcher);
上記のコードを実装する方法は次のとおりです。
verify(mock).analyze(or(eq("poppy"), endsWith("y")));
Mockito
は、
ArgumentMatchers
で共通の論理演算(「not」、「and」、「or」)を実装するための
AdditionalMatchers
も提供します。これらは、プリミティブ型と非プリミティブ型の両方に一致します。
verify(mock).analyze(or(eq("poppy"), endsWith("y")));
4.カスタム引数マッチ
私たちの
matcher
を作成することは、与えられたシナリオに対して可能な限り最善のアプローチを選択し、最高品質のテスト** を生成するのに良いことです。
たとえば、メッセージを配信する
MessageController
があります。それは
MessageDTO
を受け取り、そこから
MessageService
によって配信される
Message
を作成します。
確認は簡単です。ManyageServiceを__any Messageで1回呼び出したことを確認します。
verify(messageService, times(1)).deliverMessage(any(Message.class));
-
Message
はテスト中のメソッド内で構築されているため、
matcher
として
any
を使用する必要があります。
このアプローチでは、
Message
、
内のデータを検証することはできません。これは、
MessageDTO
内のデータとは異なる場合があります。
そのため、カスタム引数マッチャーを実装します。
public class MessageMatcher implements ArgumentMatcher<Message> {
private Message left;
//constructors
@Override
public boolean matches(Message right) {
return left.getFrom().equals(right.getFrom()) &&
left.getTo().equals(right.getTo()) &&
left.getText().equals(right.getText()) &&
right.getDate() != null &&
right.getId() != null;
}
}
-
マッチャーを使うには、テストを修正して
any
を
argThat
** に置き換える必要があります。
verify(messageService, times(1)).deliverMessage(argThat(new MessageMatcher(message)));
これで、
Message
インスタンスは
MessageDTO
と同じデータを持つことがわかりました。
5.カスタム引数マッチャーと
ArgumentCaptor
両方のテクニック
カスタム引数matchers
と
ArgumentCaptor
を使用して、特定の引数がモックに渡されるようにすることができます。
ただし、検証を完了するために引数値をアサートする必要がある場合、またはカスタム引数matcher
が再利用される可能性がない場合は、
ArgumentCaptor__が適している可能性があります 。
ArgumentMatcher
を介した
カスタム引数matchers
は、通常スタブ処理に適しています。
6.まとめ
この記事では、
Mockito
、
ArgumentMatcher
の機能、および__ArgumentCaptorとの違いについて説明しました
いつものように、例の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-mockito[over on GitHub]から入手可能です。