31

メソッド呼び出しのパラメーターが特定のタイプであるモックとの相互作用の数を確認するには、次のようにします。

mock.someMethod(new FirstClass());
mock.someMethod(new OtherClass());
verify(mock, times(1)).someMethod(isA(FirstClass.class));

への呼び出しのおかげで、これはisA2someMethod回呼び出されましたが、引数 FirstClass で 1 回だけ呼び出されました

ただし、Captor が特定の引数用に作成された場合でも、ArgumentCaptor を使用する場合、このパターンは不可能のようです。FirstClass

これはうまくいきません

mock.someMethod(new FirstClass());
mock.someMethod(new OtherClass());
ArgumentCaptor<FirstClass> captor = ArgumentCaptor.forClass(FirstClass.class);
verify(mock, times(1)).someMethod(captor.capture());

モックが複数回呼び出されたと言います。

さらにチェックするために引数を取得しながら、この検証を行う方法はありますか?

4

4 に答える 4

32

Mockito の Hamcrest 統合を使用して、適切でクリーンなマッチャーを作成することをお勧めします。これにより、検証と渡された引数の詳細なチェックを組み合わせることができます。

import static org.mockito.hamcrest.MockitoHamcrest.argThat;

verify(mock, times(1)).someMethod(argThat(personNamed("Bob")));

Matcher<Person> personNamed(final String name) {
    return new TypeSafeMatcher<Person>() {
        public boolean matchesSafely(Person item) {
            return name.equals(item.getName());
        }
        public void describeTo(Description description) {
            description.appendText("a Person named " + name);
        }
    };
}

通常、Matcher は、より読みやすいテストと、より有用なテスト失敗メッセージにつながります。また、それらは非常に再利用可能である傾向があり、プロジェクトのテスト用に調整されたそれらのライブラリを構築していることに気付くでしょう。最後に、JUnit の を使用して通常のテスト アサーションにも使用できるため、それらをAssert.assertThat()二重に使用できます。

于 2013-06-20T03:58:00.547 に答える
0

今日もこの問題に遭遇しました。私は単に次のようなことができると思った

verify(mock).someMethod(and(isA(FirstClass.class), captor.capture()));

しかし、私はそれを機能させることができませんでした。私はこの解決策になりました:

@Test
public void Test() throws Exception {
    final ArgumentCaptor<FirstClass> captor = ArgumentCaptor.forClass(FirstClass.class);

    mock.someMethod(new FirstClass());
    mock.someMethod(new OtherClass());

    verify(eventBus, atLeastOnce()).post(captor.capture());
    final List<FirstClass> capturedValues = typeCheckedValues(captor.getAllValues(), FirstClass.class);
    assertThat(capturedValues.size(), is(1));
    final FirstClass capturedValue = capturedValues.get(0);
    // Do assertions on capturedValue
}

private static <T> List<T> typeCheckedValues(List<T> values, Class<T> clazz) {
    final List<T> typeCheckedValues = new ArrayList<>();
    for (final T value : values) {
        if (clazz.isInstance(value)) {
            typeCheckedValues.add(value);
        }
    }
    return typeCheckedValues;
}

注: この方法で 1 つのクラスのみをキャプチャする必要がある場合は、次のようtypeCheckedValuesに簡略化できます。

private static List<FirstClass> typeCheckedValues(List<FirstClass> values) {
    final List<FirstClass> typeCheckedValues = new ArrayList<>();
    for (final Object value : values) {
        if (value instanceof FirstClass) {
            typeCheckedValues.add((FirstClass) value);
        }
    }
    return typeCheckedValues;
}
于 2017-01-05T10:40:39.277 に答える