異なるパラメーターで複数のメソッド呼び出しを確認する方法


115

動作を確認したい次の方法があります。

public void methodToTest(Exception e, ActionErrors errors) {
    ...

    errors.add("exception.message", 
            ActionMessageFactory.createErrorMessage(e.toString()));

    errors.add("exception.detail",
            ActionMessageFactory.createErrorMessage(e.getStackTrace()[0].toString()));

    ...
}

私の@Testクラスでerrors.add()は、「exception.message」で呼び出され、「exception.detail」で再度呼び出されることを確認するために、次のようなことを望んでいました

verify(errors).add(eq("exception.message"), any(ActionError.class));
verify(errors).add(eq("exception.detail"), any(ActionError.class));

しかしモッキートは次のように文句を言う

Argument(s) are different! Wanted:
actionErrors.add(
    "exception.message",
    <any>
);

Actual invocation has different arguments:
actionErrors.add(
    "exception.detail",
    org.apache.struts.action.ActionError@38063806
);

両方の値をチェックするようにMockitoに指示するにはどうすればよいですか?


1
署名が異なる2つのメソッドがある場合は、両方に個別のテストケースを作成できます。
Naveen Babu 2011

8
はい。ただし、この場合、メソッドシグネチャは同じですが、引数の値が異なるだけです
Brad

あなたが使用しようとすることができますMockito.reset()
takacsot

回答:


102

さらに読むと、ArgumentCaptorsと以下の作品を使用するようになりましたが、希望よりもはるかに冗長です。

ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);

verify(errors, atLeastOnce()).add(argument.capture(), any(ActionMessage.class));

List<String> values = argument.getAllValues();

assertTrue(values.contains("exception.message"));
assertTrue(values.contains("exception.detail"));

特定のパラメーターがこのアプローチを使用してペアになっていることを確認する方法はありますか?セイは、例えばOPの方法は2つの引数を持っていたし、彼らは一緒に呼ばれた検証したかったです
committedandroider

1
OPのテストケースはmethodToTest()1回だけ呼び出すため、この回答は2つの呼び出しが一緒に行われることを確認します。List<String> valuesアサートされるキャプチャーには、テストされる2つの値のみが含まれ、他の値は含まれません。追加することもできassertTrue(values.size == 2)ます。これが必要な場合は、3つのassertTrueステートメントを単一のHamcrestに置き換えます...assertThat(values, contains("exception.message", "exception.detail"));
ブラッド

OPのテストケースはmethodToTest()を2回呼び出しませんか?
コミット済みのAndroider

すみません、よくわかりませんでした。私は、OPが2つの引数が組み合わせて呼び出されることをテストしたいシナリオについて言及していました。そのため、メソッドシグネチャはpublic void methodToTest(Exception e、Message m、ActionErrors errors){のようになり、特定の例外が特定のメッセージで呼び出されます。私はあなただけ2 ArgumentCaptorsを持っていると、インデックスを取得し、両方の値のリストにそれらのインデックスで値を使用して比較することができると仮定
committedandroider

OPのテストケースがmethodToTest()1回呼び出されます。これは、メソッドの引数ActionErrors errorsが内部的に2回呼び出されることです。
Brad

60

両方のadd()呼び出しの順序が関連している場合は、次を使用できますInOrder

InOrder inOrder = inOrder(errors);
inOrder.verify(errors).add(eq("exception.message"), any(ActionError.class));
inOrder.verify(errors).add(eq("exception.detail"), any(ActionError.class));

7
単一のerrors引数を渡すだけで十分です InOrder inOrder = inOrder(errors);ドキュメントを参照)
GreenhouseVeg

2
注文が関係ない場合はどうなりますか?よくあることです。
haelix 2018

1
@haelixその場合は、Bradsの回答を使用してください。変換ListSet入力のセットは、引数の取得によって与えられたセットに等しいことと主張しています。
フロップショット

25

このようなものを試してください:

verify(errors, times(2))
     .add(AdditionalMatchers.or(eq("exception.message"), eq("exception.detail")),
          any(ActionError.class));

4
あなたのチェックは明らかにあまりにもリラックスしています。
haelix 2018

17

おそらくコードに問題があります。実際のところ、実際には次のコードを記述しているからです。

Map<Character, String> map = mock(Map.class);

map.put('a', "a");
map.put('b', "b");
map.put('c', "c");

verify(map).put(eq('c'), anyString());
verify(map).put(eq('a'), anyString());
verify(map).put(eq('b'), anyString());

最初の検証は、実際の呼び出しに関して順序が揃っていないことに注意してください。

また、所有していないタイプ(strutsタイプなど)を実際にモックしないことをお勧めします。

[編集@ブラッド]

IDEでBriceのコード(上記)を実行した後、ActionMessageではなくActionErrorを使用したことがわかります。そのため、私のverify()は一致しませんでした。最初に投稿したエラーメッセージは、一致しない最初の引数であると誤解してしまいました。それは2番目の議論だったことがわかりました。

だから私の質問への答えは

/** 
 * note that ActionMessageFactory.createErrorMessage() returns ActionMessage
 * and ActionError extends ActionMessage
 */
verify(errors).add(eq("exception.message"), any(ActionMessage.class));
verify(errors).add(eq("exception.detail"), any(ActionMessage.class));

1
あなたが言おうとしていることを理解しないでください。確認の順番は重要ですか?確認順序が重要な場合。なぜここにInOrder APIが提供されているのですか?
Oleksandr Papchenko 2016年

上記と同じように、検証順序は関係ありません。だからこそInOrder
Brice、2016年

12

Mockito.atLeastOnce()そのmockObjectが何度も呼び出される場合でも、Mockitoがテストに合格できるようにするを使用できます。

Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(1));

Mockito.verify(mockObject, Mockito.atLeastOnce()).testMethod(Mockito.eq(2));

1

1)Mokitoに電話での期待を伝えます。

2)各パラメータの組み合わせが予想される回数をMokitoに伝えます。

verify(errors, times(2)).add(any(), any(ActionMessage.class));

verify(errors, atLeastOnce()).add(eq("exception.message"), any());
verify(errors, atLeastOnce()).add(eq("exception.detail"), any());

0

@ sendon1928と同様に、以下を使用できます。

Mockito.times(wantedInvocationCount)

メソッドが正確な回数呼び出されたことを確認する(私の意見では好ましい解決策)。その後、私たちは呼び出すことができます

Mockito.verifyNoMoreInteractions(mock)

モックがどのコンテキストでも使用されていないことを確認するため。完全な例:

Mockito.verify(mockObject, Mockito.times(wantedInvocationCount)).testMethod(Mockito.eq(1));

Mockito.verify(mockObject, Mockito.times(wantedInvocationCount)).testMethod(Mockito.eq(2));

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