是否有针对varargsarrays的Mockito eq匹配器?

尝试将作为参数传递的数组匹配到接收varargs数组的方法时,我遇到了问题。

其他问题/答案中提到的anyVararg()匹配器对我不起作用,因为我想确保提供的数组是我需要的数组。

我将问题简化为这个更易于理解和抽象问题的例子(我的真正问题是生产代码并且具有业务逻辑,因此对于这个问题的目的而言会令人困惑):

@RunWith(MockitoJUnitRunner.class) public class UnitTest { private Object[] objectArray; private List expected; private TestTarget target; @Before public void setUp() { objectArray = new Object[]{ new Object() }; expected = Arrays.asList(new Object(), new Object()); target = Mockito.spy(new TestTarget()); } @Test public void testMakeList() { // this pass as eq works well with normal array doReturn(expected).when(target).toList(Mockito.eq(objectArray)); Assert.assertEquals(expected, target.makeList(objectArray)); } @Test public void testMakeList1() { // this one fails as eq is not working with varargs doReturn(expected).when(target).toList1(Mockito.eq(objectArray)); Assert.assertEquals(expected, target.makeList1(objectArray)); } @Test public void testMakeListWithAryEq() { // fails, aryEq is not working with varargs doReturn(expected).when(target).toList1(AdditionalMatchers.aryEq(objectArray)); Assert.assertEquals(expected, target.makeList1(objectArray)); } private class TestTarget { public List makeList(Object[] objects) { return toList(objects); } public List makeList1(Object[] objects) { return toList1(objects); } protected List toList(Object[] objs) { return null; // Not implemented "Intentionally" } protected List toList1(Object... objs) { return null; // Not implemented "Intentionally" } } } 

当我在类中运行测试用例时,第一个测试用例将通过而不是其他两个,既不使用eq也不使用aryEq。 显示以下跟踪:

 java.lang.AssertionError: expected: but was: at org.junit.Assert.fail(Assert.java:88) at org.junit.Assert.failNotEquals(Assert.java:743) at org.junit.Assert.assertEquals(Assert.java:118) at org.junit.Assert.assertEquals(Assert.java:144) ... 

发生这种情况是因为eq匹配器不使用varargs数组,是否有替代此用例的eq匹配器?

好吧,我认为这里的答案需要一个自定义构建的匹配器,可以在unit testing中实现,如下所示:

 private class MyVarargMatcher extends ArgumentMatcher implements VarargMatcher { private Object[] expectedValues; MyVarargMatcher(Object... expectedValues) { this.expectedValues = expectedValues; } @Override public boolean matches(Object varargArgument) { return new EqualsBuilder() .append(expectedValues, varargArgument) .isEquals(); } } 

然后,在testMakeList1()中将第一行更改为:

 Mockito.doReturn(expected).when(target).toList1(Mockito.argThat(new MyVarargMatcher(objectArray))); 

资料来源:
如何正确匹配Mockito中的varargs
http://maciejmadej.blogspot.com/2011/11/capturing-varargs-argument-using-custom.html

匹配varargs没问题。 唯一的限制是您必须将每个单独的数组条目指定为匹配的参数。 我已经更新了下面的代码以显示我的意思。 我创建了第二个objectArray2来使点更清晰。 所有测试通过:

 @RunWith(MockitoJUnitRunner.class) public class UnitTest { private Object[] objectArray; private Object[] objectArray2; private List expected; private TestTarget target; private Object obj,obj2; @Before public void setUp() { obj = new Object(); obj2 = new Object(); objectArray = new Object[]{ obj }; objectArray2 = new Object[]{ obj, obj2 }; expected = Arrays.asList(new Object(), new Object()); target = Mockito.spy(new TestTarget()); } @Test public void testMakeList() { // this pass as eq works well with normal array doReturn(expected).when(target).toList(Mockito.eq(objectArray)); Assert.assertEquals(expected, target.makeList(objectArray)); } @Test public void testMakeList1() { // since objectArray has one entry you need to add one matching argument doReturn(expected).when(target).toList1(Mockito.eq(obj)); Assert.assertEquals(expected, target.makeList1(objectArray)); } @Test public void testMakeListWithAryEq() { // since objectArray2 has two entries you need to add two matching arguments doReturn(expected).when(target).toList1(Mockito.eq(obj),Mockito.eq(obj2)); Assert.assertEquals(expected, target.makeList1(objectArray2)); } private class TestTarget { public List makeList(Object[] objects) { return toList(objects); } public List makeList1(Object[] objects) { return toList1(objects); } protected List toList(Object[] objs) { return null; // Not implemented "Intentionally" } protected List toList1(Object... objs) { return null; // Not implemented "Intentionally" } } }