Mockito的参数匹配

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mockito的参数匹配相关的知识,希望对你有一定的参考价值。

参考技术A 上篇我们已经说过, mockito 中可以控制mock对象的方法,返回我们想要的值,而无需真正执行它。
使用方法是 doReturn(...).when(mockObject).invokeMethod(...params)
其中

传入调用方法中的参数,可以使用Mockito中的 any() 来做参数的匹配,代表任意的值,还有 anyString() , anyInt() , any(Class<T> clazz) 等,具体可以查看 org.mockito.Matchers 。

这里我经常用到的一个是 any(Class<T> clazz) ,传入任意一个特定类型的对象,控制方法的返回值。那如果再细化灵活一些,要根据对象的某一个属性的取值来进行匹配呢?比如要传入 Person 这个对象,测试方法要根据性别来做出不同的返回,应该怎么写参数匹配?Mockito为我们提供了 ArgumentMatcher 的方法。具体使用如下,

参考:
https://www.planetgeek.ch/2011/11/25/mockito-argumentmatcher-vs-argumentcaptor/

Mockito:使用泛型参数进行验证

【中文标题】Mockito:使用泛型参数进行验证【英文标题】:Mockito: Verifying with generic parameters 【发布时间】:2011-09-04 18:25:48 【问题描述】:

使用 Mockito,我可以做到以下几点:

verify(someService).process(any(Person.class));

但是如果process 取而代之的是Collection&lt;Person&gt;,我该怎么写呢?无法弄清楚如何正确编写它。只是遇到语法错误...

【问题讨论】:

【参考方案1】:

试试:

verify(someService).process(Matchers.<Collection<Person>>any());

实际上,当我输入 any() 时,IntelliJ 自动建议了此修复程序...不幸的是,在这种情况下您不能使用静态导入。

【讨论】:

感谢它的工作...但上帝看起来很可怕,必须有更好的方法来纠正它... 赞许唯一能回答上述问题的解决方案,而不是针对匹配容器的特殊情况。 这个答案现在不正确。下面的答案给出了一个更好的解决方案。 我可能弄错了,但我认为这不是正确的答案。虽然它删除了警告,但验证从“any(Collection.class)”切换到 any(),它不验证任何内容。至少在进行班级检查之前。不是吗? Matchers 已弃用,现在应使用 ArgumentMatchers【参考方案2】:

试试:

verify(someService).process(anyCollectionOf(Person.class));

自从版本1.8Mockito引入

public static <T> Collection<T> anyCollectionOf(Class<T> clazz);

【讨论】:

对于其他来这里并需要它的人,除了 anyCollectionOf() 之外,还有一个 anyListOf(),请参阅:***.com/a/10512526/908677 anyCollectionOf(Class clazz) 将在 Mockito 3.0 和 java8 中被删除。会有一个新方法:anyOptional(Class class) 见:github.com/mockito/mockito/issues/308【参考方案3】:

如果你使用自己的方法,你甚至可以使用静态导入:

private Collection<Person> anyPersonCollection() 
    return any();

然后就可以使用了

verify(someService).process(anyPersonCollection());

【讨论】:

【参考方案4】:

作为已接受答案的替代方案,您可以尝试:

verify(someService).process(Mockito.<SomeGenericClass<Person>>any());

我使用org.mockito.Mockito 而不是Matchers

【讨论】:

【参考方案5】:

由于类型擦除,您无法表达这一点。即使你可以用代码表达它,Mockito 也没有机会在运行时检查它。您可以创建一个类似

的界面
interface PersonCollection extends Collection<Person>  /* nothing */ 

而是在整个代码中使用它。

编辑:我错了,Mockito 有 anyCollectionOf(..) 这是你想要的。

【讨论】:

实际上,如果 API 接受它,它可以用“类型文字”对象表示:any(new TypeLiteral&lt;Collection&lt;Person&gt;&gt;() )。当然不漂亮,但它确实有效,因为所有类型信息都在运行时可用(通过反射或字节码库)。 @Rogerio:你是对的,现在看来 Mockito 确实支持这一点。好久没用了……

以上是关于Mockito的参数匹配的主要内容,如果未能解决你的问题,请参考以下文章

Mockito:等待与参数匹配的调用

OCHamcrest 匹配器参数与验证时的 Mockito 模拟不兼容

单元测试mockito参数匹配使用场景和注意项

mockito doReturn精确匹配对象实例

用于 PC Mockito 模拟验证的自定义 Hamcrest 匹配器

验证Mockito中的List列表参数