如何正确匹配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,并适当地施放它们,添加到列表或其他。