Mockito ArgumentMatchers

Mockito ArgumentMatchers

1. 概要

このチュートリアルでは、how to use the ArgumentMatcher and how it differs from the ArgumentCaptorを示します。

Mockitoフレームワークの概要については、to this articleを参照してください。

2. Mavenの依存関係

単一の成果物を追加する必要があります。


    org.mockito
    mockito-core
    2.21.0
    test

Mockitoの最新バージョンは、Maven Centralにあります。

3. ArgumentMatchers

さまざまな方法で模擬メソッドを構成することが可能です。 それらの1つは、固定値を返すことです。

doReturn("Flower").when(flowerService).analyze("poppy");

上記の例では、分析サービスがStringの「poppy」を受信した場合にのみStringの「Flower」が返されます。

しかし、maybe we need to respond to a wider range of values or beforehand unknown values

これらすべてのシナリオで、we can configure our mocked methods with argument*matchers*:

when(flowerService.analyze(anyString())).thenReturn("Flower");

これで、anyString引数マッチャーがあるため、分析に渡す値に関係なく、結果は同じになります。 ArgumentMatchersを使用すると、柔軟な検証またはスタブが可能になります。

メソッドに複数の引数がある場合、it isn’t possible to use ArgumentMatchers for only some of the argumentsMockitoでは、すべての引数を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);

matchers areを使用する場合は、さらに2つの注意点があります。

  • We can’t use them as a return value、呼び出しをスタブする場合は正確な値が必要です

  • 最後に、we can’t use argument matchers outside of verification or stubbing

最後のケースでは、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. カスタム引数マッチャー

クリーンで保守可能なour matcher can be good to select the best possible approach for a given scenario and produce highest quality testを作成します。

たとえば、メッセージを配信するMessageControllerを作成できます。 MessageDTOを受け取り、そこから、MessageServiceによって配信されるMessageを作成します。

検証は簡単です。any Message:を使用してMessageServiceを1回だけ呼び出したことを検証します。

verify(messageService, times(1)).deliverMessage(any(Message.class));

the Message is constructed inside the method under testであるため、anymatcherとして使用する必要があります。

このアプローチでは、Messagewhich can be different compared to the data inside MessageDTO内のデータを検証できません。

そのため、カスタム引数マッチャーを実装します。

public class MessageMatcher implements ArgumentMatcher {

    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;
    }
}

To use our matcher, we need to modify our test and replace any by argThat

verify(messageService, times(1)).deliverMessage(argThat(new MessageMatcher(message)));

これで、MessageインスタンスがMessageDTOと同じデータを持つことがわかりました。

5. カスタム引数マッチャーと ArgumentCaptor

custom argument matchersArgumentCaptorの両方の手法を使用して、特定の引数がモックに渡されたことを確認できます。

ただし、検証を完了するにはArgumentCaptor may be a better fit if we need it to assert on argument valuesor our custom argument matcher is not likely to be reused

ArgumentMatcherを介したCustom argument matchersは、通常、スタブに適しています。

6. 結論

この記事では、Mockito ArgumentMatcherの機能と、ArgumentCaptor.との違いについて説明しました。

いつものように、例の完全なソースコードはover on GitHubで入手できます。