【问题标题】:Java Optional.ofNullable with MockitoJava Optional.ofNullable 与 Mockito
【发布时间】:2015-12-06 22:54:00
【问题描述】:

java.utilOptional.ofNullable 可以与 Mockito 一起正常工作吗?

在代码执行过程中,我遇到了这样的事情:

User user = Optional.ofNullable(userProviderMock.findUser()).orElse(someMethod())

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

when(userProviderMock.findUser()).thenReturn(new User());

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

【问题讨论】:

  • 我认为 Mockito 没有理由干涉这里。您应该尝试找出Optional 的实际值是多少,例如通过在调用orElse 之前检查其值,或调试到该方法。
  • 当我在Optional 上调用isPresent() 时,结果是true

标签: java java-8 mockito optional


【解决方案1】:

Mockito 和 ofNullable 在这里并没有真正的问题。考虑这段代码:

Optional.of("foo").orElse(someMethod())

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

如果这对您来说是个问题——如果您不想调用 someMethod(),除非它的返回值确实需要——那么您应该改用 orElseGet

Optional.of("foo").orElseGet(() -> someMethod())

或者更确切地说:

User user = Optional.ofNullable(userProviderMock.findUser()).orElseGet(() -> someMethod())

编辑添加:Didier L指出() -> someMethod()也可以写成this::someMethod(也就是说:我们可以把它写成方法引用而不是lambda),这可能更具可读性。

无论哪种方式,它都会被隐式转换为大致如下:

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

【讨论】:

  • someMethod() 是复杂的公司逻辑,除非 Optional 为空,否则我不想调用它。总而言之,orElse()orElseGet 之间的区别在于,第一个总是在括号内调用代码,不管它是否会被使用,而第二个,只有在 Optional 为空的情况下?对吗?
  • @krzakov:呃,不完全是。 Optional 没有什么特别之处——它只是一个库类,它没有任何能力绕过 Java 代码的正常执行方式。特别是,orElse() 不会“调用”任何代码;它的参数在 orElse 被调用之前被评估,就像在 Java 中经常发生的那样。不同之处在于orElseGet() 不是在 Optional 为空时使用一个值,而是在 Optional 为空时使用一个可以调用的 Supplier 来获取要使用的值。因此,它仅在必要时才调用该供应商。这有意义吗?
  • 你也可以写orElseGet(this::someMethod)来避免写一个lambda。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-06
  • 2023-03-31
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 2023-02-04
  • 1970-01-01
相关资源
最近更新 更多