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]から入手可能です。