如何正确匹配Mockito中的可变参数

我一直在尝试使用Mockito来模拟一个使用可变参数的方法:

interface A { B b(int x, int y, C... c); } A a = mock(A.class); B b = mock(B.class); when(ab(anyInt(), anyInt(), any(C[].class))).thenReturn(b); assertEquals(b, ab(1, 2)); 

这不起作用,但是如果我这样做:

 when(ab(anyInt(), anyInt())).thenReturn(b); assertEquals(b, ab(1, 2)); 

这样做是有效的,尽pipe在保留方法的时候我完全忽略了可变参数的参数。

任何线索?

Mockito 1.8.1引入了anyVararg()匹配器 :

 when(ab(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b); 

另请参阅历史logging: https : //code.google.com/archive/p/mockito/issues/62

有些没有logging的function:如果你想开发一个匹配可变参数的自定义匹配器,你需要让它实现org.mockito.internal.matchers.VarargMatcher来正常工作。 这是一个空的标记接口,没有这个接口,当使用Matcher调用一个可变参数的方法时,Mockito不会正确地比较参数。

例如:

 class MyVarargMatcher extends ArgumentMatcher<C[]> implements VarargMatcher { @Override public boolean matches(Object varargArgument) { return /* does it match? */ true; } } when(ab(anyInt(), anyInt(), argThat(new MyVarargMatcher()))).thenReturn(b); 

build立在Eli Levine的答案是一个更通用的解决scheme:

 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的arrays匹配器,因此:

 verify(a).b(VarArgMatcher.varArgThat( org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test"))); 

(显然,静态导入会使这个更具可读性。)

根据topchef的回答,

对于2.0.31-beta,我必须使用Mockito.anyVararg而不是Matchers.anyVararrg:

 when(ab(anyInt(), anyInt(), Mockito.<String>anyVararg())).thenReturn(b); 

我一直在使用Peter Westmacott的答案代码,但是Mockito 2.2.15现在可以执行以下操作:

verify(a).method(100L, arg1, arg2, arg3)

其中arg1, arg2, arg3是可变参数。

在我的情况下,我想捕捉它的论点的方法的签名是:

  public byte[] write(byte ... data) throws IOException; 

在这种情况下,你应该明确地转换成字节数组

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

例如检查他们的types,并适当地施放它们,添加到列表或其他。