我遇到了一个关于Mockito和Hamcrest的通用问题。
请假设如下界面:
public interface Service {
void perform(Collection<String> elements);
}
和下面的测试片段:
Service service = mock(Service.class);
// ... perform business logic
verify(service).perform(Matchers.argThat(contains("a", "b")));
因此,我想验证我的业务逻辑实际上调用了一个包含“a”和“b”的集合。
但是,contains(...)
的返回类型是Matcher<Iterable<? extends E>>
,所以在我的例子中,Matchers.argThat(...)
返回Iterable<String>
,这自然不适用于所需的Collection<String>
。
我知道我可以使用Hamcrest hasItem and Mockito verify inconsistency中提出的参数捕获器,但我非常不愿意这样做。
有什么建议吗!谢谢!
7条答案
按热度按时间0ve6wy6x1#
如果您遇到类似的情况,请记住您可以编写一个非常小的可重用适配器。
请注意,上面的大卫的解决方案,与铸造,是最短的正确答案。
wi3ka0sx2#
你可以把你自己的lambda写成
ArgumentMatcher
oiopk7p53#
假设列表只包含两项,为什么不使用预期的参数进行验证,例如:
虽然我原则上同意Eugen的观点,但我认为依赖于equals进行字符串比较是可以接受的......此外,
contains
匹配器无论如何都使用equals进行比较。nhhxz33t4#
与这里的另一个答案类似,您可以执行以下操作:
b91juud35#
您可以拥有自己的java.util.Collection实现并重写equals方法,如下所示。
2jcobegt6#
你可以直接写
从编译器的Angular 来看,这是将
Iterable<String>
转换为Collection<String>
,这很好,因为后者是前者的子类型。在运行时,argThat
将返回null
,这样就可以传递给perform
,而不需要ClassCastException
。的内部结构进行验证,这是argThat
所做的。tjrkku2a7#
作为一种替代方法,可以将该方法更改为
ArgumentCaptor
:请注意,作为一个副作用,它将验证从Hamcrest库中分离出来,并允许您使用任何其他库(例如Truth):