Java varargs阵列是否有Mockito eq匹配器?

Java varargs阵列是否有Mockito eq匹配器?,java,junit,mockito,Java,Junit,Mockito,我在尝试匹配作为参数传递给接收varargs数组的方法的数组时遇到问题 其他问题/答案中提到的anyVararg()匹配器不适用于我,因为我想确保提供的数组是我需要的数组。 我将问题简化为这个更容易理解和抽象问题的示例(我真正的问题是生产代码,并且有业务逻辑,因此就这个问题而言,它会令人困惑): @RunWith(MockitoJUnitRunner.class) 公共类单元测试{ 私有对象[]对象数组; 预计有私人名单; 私有测试目标; @以前 公共作废设置(){ objectArray=新对

我在尝试匹配作为参数传递给接收varargs数组的方法的数组时遇到问题

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

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

@RunWith(MockitoJUnitRunner.class)
公共类单元测试{
私有对象[]对象数组;
预计有私人名单;
私有测试目标;
@以前
公共作废设置(){
objectArray=新对象[]{new Object()};
预期=Arrays.asList(新对象(),新对象());
target=Mockito.spy(新的TestTarget());
}
@试验
public void testMakeList(){//此过程作为eq在普通数组中运行良好
doReturn(预期).when(目标).toList(Mockito.eq(objectArray));
Assert.assertEquals(应为target.makeList(objectArray));
}
@试验
public void testMakeList1(){//由于eq未使用varargs,因此此测试失败
doReturn(预期).when(目标).toList1(Mockito.eq(objectArray));
Assert.assertEquals(应为target.makeList1(objectArray));
}
@试验
public void testMakeListWithAryEq(){//失败,aryEq无法使用varargs
doReturn(预期).when(目标).toList1(AdditionalMatchers.aryEq(objectArray));
Assert.assertEquals(应为target.makeList1(objectArray));
}
私有类测试目标{
公共列表生成列表(对象[]对象){
返回列表(对象);
}
公共列表makeList1(对象[]对象){
返回到列表1(对象);
}
受保护列表列表(对象[]objs){
返回null;//未“故意”实现
}
受保护列表toList1(对象…objs){
返回null;//未“故意”实现
}
}
}
当我在类中运行测试用例时,第一个测试用例将通过,但其他两个测试用例不会通过,既不使用eq也不使用aryEq。显示以下跟踪:

java.lang.AssertionError: expected:<[java.lang.Object@56d5e457, java.lang.Object@7482384a]> but was:<null>
    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)
    ...
java.lang.AssertionError:应为:但为:
位于org.junit.Assert.fail(Assert.java:88)
位于org.junit.Assert.failNotEquals(Assert.java:743)
位于org.junit.Assert.assertEquals(Assert.java:118)
位于org.junit.Assert.assertEquals(Assert.java:144)
...

发生这种情况是因为eq匹配器不使用varargs阵列,对于这个用例,eq匹配器还有其他选择吗?

好的,我认为这里的答案需要一个定制的匹配器,它可以在您的单元测试中实现,因此:

private class MyVarargMatcher extends ArgumentMatcher<Object[]> implements VarargMatcher {
    private Object[] expectedValues;

    MyVarargMatcher(Object... expectedValues) {
        this.expectedValues = expectedValues;
    }

    @Override
    public boolean matches(Object varargArgument) {
        return new EqualsBuilder()
        .append(expectedValues, varargArgument)
        .isEquals();
    }
}
资料来源:


匹配vararg没有问题。唯一的限制是必须将每个单独的数组项指定为匹配的参数。我已经在下面更新了你的代码来说明我的意思。我创建了第二个objectArray2来更清楚地说明这一点。所有测试均通过:

@RunWith(MockitoJUnitRunner.class)
public class UnitTest {
    private Object[] objectArray;
    private Object[] objectArray2;
    private List<Object> 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<Object> makeList(Object[] objects) {
            return toList(objects);
        }

        public List<Object> makeList1(Object[] objects) {
            return toList1(objects);
        }

        protected List<Object> toList(Object[] objs) {
            return null;  // Not implemented "Intentionally"
        }

        protected List<Object> toList1(Object... objs) {
            return null;  // Not implemented "Intentionally"
        }
    }
}
@RunWith(MockitoJUnitRunner.class)
公共类单元测试{
私有对象[]对象数组;
私有对象[]objectArray2;
预计有私人名单;
私有测试目标;
私有对象obj,obj2;
@以前
公共作废设置(){
obj=新对象();
obj2=新对象();
objectArray=新对象[]{obj};
objectArray2=新对象[]{obj,obj2};
预期=Arrays.asList(新对象(),新对象());
target=Mockito.spy(新的TestTarget());
}
@试验
public void testMakeList(){//此过程作为eq在普通数组中运行良好
doReturn(预期).when(目标).toList(Mockito.eq(objectArray));
Assert.assertEquals(应为target.makeList(objectArray));
}
@试验
public void testMakeList1(){//,因为objectArray有一个条目,所以需要添加一个匹配参数
doReturn(预期).when(目标).toList1(Mockito.eq(obj));
Assert.assertEquals(应为target.makeList1(objectArray));
}
@试验
public void testMakeListWithAryEq(){//,因为objectArray2有两个条目,所以需要添加两个匹配的参数
doReturn(预期).when(目标).toList1(Mockito.eq(obj),Mockito.eq(obj2));
Assert.assertEquals(应为target.makeList1(objectArray2));
}
私有类测试目标{
公共列表生成列表(对象[]对象){
返回列表(对象);
}
公共列表makeList1(对象[]对象){
返回到列表1(对象);
}
受保护列表列表(对象[]objs){
返回null;//未“故意”实现
}
受保护列表toList1(对象…objs){
返回null;//未“故意”实现
}
}
}

正如我在问题中提到的,显示的代码是一个示例,可以很容易地看到matcher如何不使用varargs。我所发布的代码是我公司的财产,并且具有我无法共享的带有业务逻辑的生产样式代码。问题是,如果有一个匹配器的等价物将与varargsOk一起使用,我已经为您创建了一个自定义匹配器供您使用,请让我知道它是否有效。答案似乎是:不,目前Mockito中没有针对varargs的eq等价匹配器,但是我们可以创建一个类似于您和您所引用的博客文章。我实现了我的方法,还添加了一个提取匹配器调用的方法,这样我就可以像这样编写eqVararg(objectArray):private Object[]eqVararg(Object…vararg){return Mockito.argThat(new VarargsMatcher(vararg));}我已经将您的自定义匹配器移植到Scala。详情如下:
Mockito.doReturn(expected).when(target).toList1(Mockito.argThat(new MyVarargMatcher(objectArray)));
@RunWith(MockitoJUnitRunner.class)
public class UnitTest {
    private Object[] objectArray;
    private Object[] objectArray2;
    private List<Object> 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<Object> makeList(Object[] objects) {
            return toList(objects);
        }

        public List<Object> makeList1(Object[] objects) {
            return toList1(objects);
        }

        protected List<Object> toList(Object[] objs) {
            return null;  // Not implemented "Intentionally"
        }

        protected List<Object> toList1(Object... objs) {
            return null;  // Not implemented "Intentionally"
        }
    }
}