Use Mockito 2.0.7 to mock lambda expressions

29,469

Solution 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

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.

Share:
29,469
Christoph
Author by

Christoph

Updated on April 09, 2020

Comments

  • Christoph
    Christoph about 4 years

    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?