在 Java 单元测试中,如何验证函数类型的变量被调用时传入了某些参数?

In Java unit testing, how to verify a variable of type Function is called with certain arguments passed in?

我有一个 Function 类型的变量,例如:

Class SomeClass{ 
    static final Function<Throwable, Optional<String>> SOME_FUNCTION = throwable -> Optional.empty();
}

我想知道如何验证它在特定时间被调用并在特定参数中被传递?

我需要的是以下代码的等价物:

verify(SomeClass, times(2)).SOME_FUNCTION(any(Exception.class));

提前致谢!

您需要将 SOME_FUNCTION 替换为可以断言调用的 Mockito 模拟。根据您的情况,可能有几种方法可以实现此目的:

作为成员传入函数

如果您需要对其执行断言的函数不一定需要是最终静态的,并且在您的情况下传递它是有意义的:

class MyClass {
    final Function<Throwable, Optional<String>> someFunction;

    public MyClass(Function<Throwable, Optional<String>> someFunction) {
        this.someFunction = someFunction;
    }

    // ...
}

然后你可以在你的测试中传递一个模拟:

Function<Throwable, Optional<String>> mockFunc = Mockito.mock(Function.class);
var myClass = new MyClass(mockFunc);
// ... test code ...
verify(mockFunc, times(2)).apply(any(Exception.class));

如果函数需要保持静态,但您仍然可以创建变量 non-final,那么您只需通过静态赋值来更改它,它应该可以正常工作。在这种情况下,请记住之后将其设置回原始值。

使用反射模拟静态成员

如果您无法更改 class' 代码,并且 需要 对静态函数执行断言,它会变得有点棘手。您可以尝试使用反射将函数替换为模拟。 Mockito 有一个 Whitebox class 封装了其中的一些:

Function<Throwable, Optional<String>> mockFunc = Mockito.mock(Function.class);
Whitebox.setInternalState(MyClass.class, "SOME_FUNCTION", mockFunc);
// ... test code ...
verify(mockFunc, times(2)).apply(any(Exception.class));

但这很可能会产生一些不必要的副作用(例如 SOME_FUNCTION 模拟时间比预期的长),并且只能作为最后的手段。