Mockito 和 Hamcrest:如何验证 Collection 参数的调用?

新手上路,请多包涵

我遇到了 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”的集合调用了服务。

However, the return type of contains(...) is Matcher<Iterable<? extends E>> , so Matchers.argThat(...) returns Iterable<String> in my case, which naturally does not apply to the required Collection<String>

我知道我可以使用 Hamcrest hasItem 和 Mockito verify inconsistency 中提出的参数捕获器,但我非常不想这样做。

有什么建议么!谢谢!

原文由 Philipp Jardas 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 621
2 个回答

你可以只写

verify(service).perform((Collection<String>) Matchers.argThat(contains("a", "b")));

从编译器的角度来看,这是将 Iterable<String> 转换为 Collection<String> 这很好,因为后者是前者的子类型。 At run time, argThat will return null , so that can be passed to perform without a ClassCastException .关于它的重要一点是匹配器进入 Mockito 的内部参数结构以进行验证,这就是 argThat 所做的。

原文由 Dawood ibn Kareem 发布,翻译遵循 CC BY-SA 3.0 许可协议

作为一种替代方法,可以将方法更改为 ArgumentCaptor

 @SuppressWarnings("unchecked") // needed because of `List<String>.class` is not a thing
// suppression can be worked around by using @Captor on a field
ArgumentCaptor<List<String>> captor = ArgumentCaptor.forClass(List.class);

verify(service).perform(captor.capture());
assertThat(captor.getValue(), contains("a", "b"));

请注意,作为副作用,这将验证与 Hamcrest 库分离,并允许您使用任何其他库(例如 Truth):

 assertThat(captor.getValue()).containsExactly("a", "b");

原文由 TWiStErRob 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题