Mockito:如何匹配String和List <string>参数

时间:2015-06-03 22:14:33

标签: java unit-testing mockito

我基本上是在尝试验证是否在方法中调用了正确的参数。

以下是我要测试的代码片段:

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中传递正确的字符串

1 个答案:

答案 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