我基本上是在尝试验证是否在方法中调用了正确的参数。
以下是我要测试的代码片段:
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.in("type", Arrays.asList("employee", "supervisor");
使用以下方式验证:
Mockito.verify(mockSession).createCriteria(User.class);
Mockito.verify(mockCriteria).add(Restrictions.in("type", Arrays.asList("employee", "supervisor"));
第一个验证声明有效。第二个不是因为,我相信,JVM检测到两个不同的List
对象进行比较。但是,当我将第二个验证语句更改为:
Mockito.verify(mockCriteria).add(Restrictions.in("type", Mockito.anyList());
它就像一个魅力。但是,我确实希望确保两个字符串,员工和主管都在List
内,并且使用Mockito.anyList()
不会发生这种情况。
如何让它发挥作用?
编辑:请注意,我不想仅核实是否已通过名单。我想确保在List中传递正确的字符串
答案 0 :(得分:2)
不幸的是,在这里你不能轻易地检查你想用匹配器检查什么。
Mockito matchers work via side-effects,其中对匹配器的调用告诉Mockito使用匹配器而不是测试相等性。这意味着 Mockito匹配器在嵌套在Criterion 等对象中时根本不起作用。
verify(mockCriteria).add(
Restrictions.in("type", Arrays.asList("employee", "supervisor"));
在上文中,您不使用匹配器,而是验证使用mockCriteria.add
您指定的标准的对象调用equals
。但是,如果返回的Criterion不会覆盖equals
(和hashCode
),那么它只会测试实例是否相同 - 这在此处永远不会成立,因为您正在创建一个新实例在verify
声明中。
verify(mockCriteria).add(Restrictions.in("type", anyList()));
在这里,看起来像你正在验证是否使用任何列表调用mockCriteria.add
,但anyList()
实际上告诉Mockito跳过检查一个参数并返回虚拟对象价值null
。然后,您在null
中创建一个标准“type”,然后Mockito在堆栈上看到一个any
匹配器进行单参数方法调用,丢弃新创建的无效标准,然后检查add
被召唤了。看起来一切正常,但您的mockCriteria
可以从字面上接收任何参数,包括null
,测试仍会通过。 (如果您使用的是第二个匹配器,或者如果add
使用了两个参数,那么您将获得InvalidUseOfMatchersException
而不是误报。)
要使用Mockito匹配器进行此操作,您需要编写与您的整个Criterion匹配的Hamcrest匹配器,然后使用argThat
让Mockito与其匹配参数。
正如Andy Turner所说,解决这个问题的一种方法是使用ArgumentCaptor
:
ArgumentCaptor<Criterion> captor = ArgumentCaptor.forClass(Criterion.class);
verify(mockCriteria).add(captor.capture());
Criterion criterion = captor.getValue();
// assert against criterion
但是,请注意,这可能用途有限:Criterion没有很多可以检查的属性。您可能需要使用toString()
,如this SO question。