使用 Mockito 的通用“any()";方法

2022-01-08 00:00:00 mocking unit-testing mockito java

我有一个接口,它带有一个需要 Foo 数组的方法:

I have an interface with a method that expects an array of Foo:

public interface IBar {
  void doStuff(Foo[] arr);
}

我正在使用 Mockito 模拟这个接口,我想断言 doStuff() 被调用,但我不想验证传递了什么参数 - 不在乎".

I am mocking this interface using Mockito, and I'd like to assert that doStuff() is called, but I don't want to validate what argument are passed - "don't care".

如何使用通用方法 any() 而不是 anyObject() 编写以下代码?

How do I write the following code using any(), the generic method, instead of anyObject()?

IBar bar = mock(IBar.class);
...
verify(bar).doStuff((Foo[]) anyObject());

推荐答案

从 Java 8 开始,您可以使用无参数的 any 方法,编译器会推断类型参数:

Since Java 8 you can use the argument-less any method and the type argument will get inferred by the compiler:

verify(bar).doStuff(any());


说明

Java 8 中的新功能是 表达式的目标类型 将用于推断其子表达式的类型参数.在 Java 8 之前,只有用于类型参数推断的方法的参数(大部分时间).


Explanation

The new thing in Java 8 is that the target type of an expression will be used to infer type parameters of its sub-expressions. Before Java 8 only arguments to methods where used for type parameter inference (most of the time).

在这种情况下,doStuff的参数类型将是any()的目标类型,any() 将被选择以匹配该参数类型.

In this case the parameter type of doStuff will be the target type for any(), and the return value type of any() will get chosen to match that argument type.

添加此机制主要是为了能够编译 lambda 表达式,但它总体上改进了类型推断.

This mechanism was added mainly to be able to compile lambda expressions, but it improves type inferences generally.

不幸的是,这不适用于原始类型:

This doesn't work with primitive types, unfortunately:

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.在将返回值传递给 doStuff 之前,运行时将尝试通过调用 intValue 方法将返回值拆箱,并引发异常.

The problem is that the compiler will infer Integer as the return value type of any(). Mockito will not be aware of this (due to type erasure) and return the default value for reference types, which is null. The runtime will try to unbox the return value by calling the intValue method on it before passing it to doStuff, and the exception gets thrown.

相关文章