私はMockitoを使用して可変引数パラメータを使用してメソッドを模擬しようとしています:
interface A {
B b(int x, int y, C... c);
}
A a = mock(A.class);
B b = mock(B.class);
when(a.b(anyInt(), anyInt(), any(C[].class))).thenReturn(b);
assertEquals(b, a.b(1, 2));
これは機能しませんが、代わりにこれを行うと:
when(a.b(anyInt(), anyInt())).thenReturn(b);
assertEquals(b, a.b(1, 2));
メソッドをスタブするときにvarargs引数を完全に省略したにもかかわらず、これは機能します。
手がかりはありますか?
Mockito 1.8.1が導入されました anyVararg()matcher :
when(a.b(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b);
この履歴も参照してください: https://code.google.com/archive/p/mockito/issues/62
Edit廃止後の新しい構文:
when(a.b(anyInt(), anyInt(), ArgumentMatchers.<String>any())).thenReturn(b);
多少文書化されていない機能:vararg引数に一致するカスタムマッチャーを開発する場合、org.mockito.internal.matchers.VarargMatcher
を実装して正しく動作させる必要があります。これは空のマーカーインターフェイスです。これがない場合、Mockitoは、Matcherを使用して可変引数でメソッドを呼び出すときに引数を正しく比較しません。
例えば:
class MyVarargMatcher extends ArgumentMatcher<C[]> implements VarargMatcher {
@Override public boolean matches(Object varargArgument) {
return /* does it match? */ true;
}
}
when(a.b(anyInt(), anyInt(), argThat(new MyVarargMatcher()))).thenReturn(b);
ここでのEli Levineの答えに基づいて、より一般的なソリューションを作成します。
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.mockito.ArgumentMatcher;
import org.mockito.internal.matchers.VarargMatcher;
import static org.mockito.Matchers.argThat;
public class VarArgMatcher<T> extends ArgumentMatcher<T[]> implements VarargMatcher {
public static <T> T[] varArgThat(Matcher<T[]> hamcrestMatcher) {
argThat(new VarArgMatcher(hamcrestMatcher));
return null;
}
private final Matcher<T[]> hamcrestMatcher;
private VarArgMatcher(Matcher<T[]> hamcrestMatcher) {
this.hamcrestMatcher = hamcrestMatcher;
}
@Override
public boolean matches(Object o) {
return hamcrestMatcher.matches(o);
}
@Override
public void describeTo(Description description) {
description.appendText("has varargs: ").appendDescriptionOf(hamcrestMatcher);
}
}
次に、hamcrestの配列マッチャーで次のように使用できます。
verify(a).b(VarArgMatcher.varArgThat(
org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test")));
(明らかに、静的インポートはこれをより読みやすくします。)
私はPeter Westmacottの回答のコードを使用していますが、Mockito 2.2.15では次のことができるようになりました。
verify(a).method(100L, arg1, arg2, arg3)
どこ arg1, arg2, arg3
は可変引数です。
Topchefの答えに基づいて、
2.0.31-betaの場合、Matchers.anyVararrgの代わりにMockito.anyVarargを使用する必要がありました。
when(a.b(anyInt(), anyInt(), Mockito.<String>anyVararg())).thenReturn(b);
@topchefからの回答を適応させ、
Mockito.when(a.b(Mockito.anyInt(), Mockito.anyInt(), Mockito.any())).thenReturn(b);
Java Mockito 2.23.4のドキュメント、Mockito.any() "nullやvarargsを含むあらゆるものに一致します。"
私の場合、引数を取得したいメソッドのシグネチャは次のとおりです。
public byte[] write(byte ... data) throws IOException;
この場合、明示的にbyte arrayにキャストする必要があります。
when(spi.write((byte[])anyVararg())).thenReturn(someValue);
私はmockitoバージョンを使用しています1.10.19
引数をループすることもできます:
Object[] args = invocation.getArguments();
for( int argNo = 0; argNo < args.length; ++argNo) {
// ... do something with args[argNo]
}
たとえば、タイプをチェックして適切にキャストしたり、リストに追加したりします。