krzakov
krzakov

Reputation: 4111

Java Optional.ofNullable with Mockito

Does java.util Optional.ofNullable works properly with Mockito?

During the code execution I encounter something like this:

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

I set my mock behaviour like following:

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

When I run it, userProviderMock returns new User() (debug confirms that), but somehow someMethod() is still executed. I have literally no idea why this is happening. Any clues?

Upvotes: 3

Views: 5869

Answers (1)

ruakh
ruakh

Reputation: 183484

Mockito and ofNullable aren't really at issue here. Consider this code:

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

The above code will evaluate to Optional.of("foo") — but it still calls orElse, so it still has to call someMethod() in order to pass its return-value as an argument to orElse, even though that argument ends up not being used.

If this is a problem for you — if you don't want someMethod() to be called unless its return-value is actually needed — then you should use orElseGet instead:

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

or rather:

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

Edited to add: Didier L points out that () -> someMethod() can also be written as this::someMethod (that is: we can write it as a method reference rather than a lambda), which is probably more readable.

Either way, it gets converted implicitly to approximately this:

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

Upvotes: 8

Related Questions