【问题标题】:Using Mockito's generic "any()" method使用 Mockito 的通用“any()”方法
【发布时间】: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());

【问题讨论】:

    标签: java unit-testing mocking mockito


    【解决方案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 已弃用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    • 2016-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多