使用 Mockito 的通用“any()”方法
Posted
技术标签:
【中文标题】使用 Mockito 的通用“any()”方法【英文标题】:Using Mockito's generic "any()" method 【发布时间】:2010-12-19 05:20:02 【问题描述】:我有一个接口,它带有一个需要 Foo
数组的方法:
public interface IBar
void doStuff(Foo[] arr);
我正在使用 Mockito 模拟这个接口,我想断言 doStuff()
被调用,但我不想验证传递了什么参数 - “不在乎”。
如何使用泛型方法any()
而不是anyObject()
编写以下代码?
IBar bar = mock(IBar.class);
...
verify(bar).doStuff((Foo[]) anyObject());
【问题讨论】:
【参考方案1】:从 Java 8 开始,您可以使用无参数的 any
方法,编译器将推断类型参数:
verify(bar).doStuff(any());
说明
Java 8 中的新功能是表达式的target type 将用于推断其子表达式的类型参数。在 Java 8 之前,只有用于类型参数推断的方法的参数(大部分时间)。
在这种情况下,doStuff
的参数类型将是any()
的目标类型,any()
的返回值类型将被选择以匹配该参数类型。
添加此机制主要是为了能够编译 lambda 表达式,但它总体上改进了类型推断。
原始类型
不幸的是,这不适用于原始类型:
public interface IBar
void doPrimitiveStuff(int i);
verify(bar).doPrimitiveStuff(any()); // Compiles but throws NullPointerException
verify(bar).doPrimitiveStuff(anyInt()); // This is what you have to do instead
问题是编译器会将Integer
推断为any()
的返回值类型。 Mockito 不会意识到这一点(由于类型擦除)并返回引用类型的默认值,即null
。运行时将尝试通过调用 intValue
方法将返回值拆箱,然后将其传递给 doStuff
,并引发异常。
【讨论】:
每次这个答案获得赞成票时,我都会感到惊喜!我猜想这个问题自 Java 8 以来不会引起太多关注,因为any
方法应该可以正常工作。您不会为正常工作的事情寻找答案!
我来到这里是因为我不知道为什么我的代码不能与 any()
一起使用,但可以与 anyBoolean()
一起使用,您答案的最后一部分很好地阐明了这一点。【参考方案2】:
因为我需要在我的最新项目中使用此功能(我们曾从 1.10.19 更新),只是为了留住用户(已经在使用 mockito-core 2.1.0 或更高版本) 最新,以上答案中的静态方法应取自ArgumentMatchers
类:
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.any;
如果您计划从版本 3 开始更新您的 Mockito 人工制品,请记住这一点,此类可能不再存在:
根据 2.1.0 及更高版本,org.mockito.Matchers 的 Javadoc 声明:
使用
org.mockito.ArgumentMatchers
。这个类现在已被弃用,以便 避免与 Hamcrest 的名称冲突 *org.hamcrest.Matchers
班级。此类可能会在 3.0 版中被删除。
如果您想进一步阅读,我已经在mockito wildcards 上写了一篇小文章。
【讨论】:
如何在 Scala 中导入 org.mockito.ArgumentMatcher?我试过 import org.mockito.ArgumentMatcher.any 我得到错误 `value any is not a member of object org.mockito.ArgumentMatcher 您能告诉我 3.0 版中的等价物是什么吗? 一旦发布就知道了;)【参考方案3】:这应该可行
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
verify(bar).DoStuff(any(Foo[].class));
【讨论】:
以防万一有人在 Scala 中需要它:verify(bar).DoStuff(any[Array[Foo]])
我在导入时遇到了问题,我在导入时使用了来自 hamcrest 的 any(),但它与来自 mockito 的相撞。
请看一下API,class参数只是用于转换,方法仍然接受任何类型的对象! site.mockito.org/mockito/docs/current/org/mockito/…。在这种情况下使用 isA() site.mockito.org/mockito/docs/current/org/mockito/….
这个类现在已被弃用,以避免与 Hamcrest 发生名称冲突。使用 org.mockito.ArgumentMatchers【参考方案4】:
您可以为此使用Mockito.isA()
:
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.verify;
verify(bar).doStuff(isA(Foo[].class));
http://site.mockito.org/mockito/docs/current/org/mockito/Matchers.html#isA(java.lang.Class)
【讨论】:
这是正确答案。使用 any(Clazz) 是完全错误的。 @SurasinTancharoen 实际上, any(Class) 只是 isA(Class) 的别名(请参阅文档)。所以这完全没有错。 isA 已弃用以上是关于使用 Mockito 的通用“any()”方法的主要内容,如果未能解决你的问题,请参考以下文章
测试类时,使用 Junit 和 Mockito 检查方法内部的工作