'Use Mockito 2.0.7 to mock lambda expressions

I want to mock a query provided on my repository like this:

@Test
public void GetByEmailSuccessful() {
    // setup mocks
    Mockito.when(this.personRepo.findAll()
            .stream()
            .filter(p -> (p.getEmail().equals(Mockito.any(String.class))))
            .findFirst()
            .get())
            .thenReturn(this.personOut);
    Mockito.when(this.communityUserRepo.findOne(this.communityUserId))
            .thenReturn(this.communityUserOut);
...

My @Before method looks like this:

@Before
public void initializeMocks() throws Exception {
    // prepare test data.
    this.PrepareTestData();

    // init mocked repos.
    this.personRepo = Mockito.mock(IPersonRepository.class);
    this.communityUserRepo = Mockito.mock(ICommunityUserRepository.class);
    this.userProfileRepo = Mockito.mock(IUserProfileRepository.class);
}

Sadly when I run the test I receive the error:

java.util.NoSuchElementException: No value present

When I double-click the error it points at the .get() method of the first lambda.

Have any of you successfully mocked a lambda expression and know how I can solve my problem?



Solution 1:[1]

There's no need to mock such deep calls. Simply mock personRepo.findAll() and let the Streaming API work as normal:

Person person1 = ...
Person person2 = ...
Person person3 = ...
List<Person> people = Arrays.asList(person1, person2, ...);
when(personRepo.findAll()).thenReturn(people);

And then instead of

.filter( p -> (p.getEmail().equals(Mockito.any(String.class))) )

just set/mock email on your Person objects to be the expected value.

Alternatively, consider implementing PersonRepo.findByEmail.

Solution 2:[2]

Two things:

Mockito.when(this.personRepo.findAll()
      .stream()
      .filter(p -> (p.getEmail().equals(Mockito.any(String.class))))
      .findFirst()
      .get())
    .thenReturn(this.personOut);

First, you're trying to mock a chain of five different method calls. Mockito doesn't handle this very well; though the RETURNS_DEEP_STUBS answer (if put on personRepo) would save and return stub objects where applicable, each call to when will itself stub exactly one call.

Second, Mockito matchers aren't flexible enough to work deeply in calls; calls to when should contain exactly one method call without chaining, and calls to Mockito matchers like any should stand in for exactly one of the arguments in that method. The way you have it, you're creating a predicate p -> (p.getEmail().equals(null)) and leaving a matcher on the stack to break things later.

Use Alex Wittig's answer to solve this problem, and be mindful of stubbing and using matchers correctly in future problems.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JohnK
Solution 2 Alex Wittig