使用 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()”方法的主要内容,如果未能解决你的问题,请参考以下文章

带有 scala 的 mockito:匹配器问题

Mockito各场景使用介绍

测试类时,使用 Junit 和 Mockito 检查方法内部的工作

使用 Mockito 从模拟中抛出已检查的异常

Mockito Matchers isA、any、eq 和 same 有啥区别?

mock对象返回具有相同参数的真实对象