带有Mockito的Java Optional.ofNullable

krz*_*kov 1 java mockito optional java-8

是否java.util Optional.ofNullable工作正常使用的Mockito?

在代码执行期间,我遇到这样的事情:

User user = Optional.ofNullable(userProviderMock.findUser()).orElse(someMethod())
Run Code Online (Sandbox Code Playgroud)

我设置我的模拟行为如下:

when(userProviderMock.findUser()).thenReturn(new User());
Run Code Online (Sandbox Code Playgroud)

当我运行它时,userProviderMock返回new User()(调试确认),但不知何故someMethod()仍然执行.我真的不知道为什么会这样.有线索吗?

rua*_*akh 5

Mockito ofNullable并不是真正的问题.考虑以下代码:

Optional.of("foo").orElse(someMethod())
Run Code Online (Sandbox Code Playgroud)

上面的代码将评估为Optional.of("foo")- 但它仍然调用 orElse,所以它仍然必须调用someMethod()以将其返回值作为参数传递给orElse,即使该参数最终没有被使用.

如果这对你来说是一个问题 - 如果你不想someMethod()被调用,除非实际需要它的返回值 - 那么你应该使用orElseGet:

Optional.of("foo").orElseGet(() -> someMethod())
Run Code Online (Sandbox Code Playgroud)

更确切地说:

User user = Optional.ofNullable(userProviderMock.findUser()).orElseGet(() -> someMethod())
Run Code Online (Sandbox Code Playgroud)

编辑添加: Didier L指出() -> someMethod()也可以写成this::someMethod(即:我们可以将其编写为方法参考而不是lambda),这可能更具可读性.

无论哪种方式,它都会隐式转换为大约这样:

User user = Optional.ofNullable(userProviderMock.findUser()).orElseGet(new Supplier<User>() {
    public User get() {
        return someMethod();
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 你也可以编写`orElseGet(this :: someMethod)`以避免编写lambda. (4认同)
  • @krzakov:呃,不太好."可选"并没有什么特别之处 - 它只是一个库类,它没有任何能够规避Java代码执行的正常方式.特别是,`orElse()`不会"调用"任何代码; 在调用*`orElse`之前对其参数进行求值*,就像在Java中一样.不同之处在于`orElseGet()`,而不是在Optional为空时使用值,而是当可选为空时,它可以调用*get*要使用的值.因此,只有在必要时才会调用该供应商.那有意义吗? (3认同)