5

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?

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
Christoph
  • 438
  • 1
  • 6
  • 14
  • I might be wrong but I think you must specify a return value for `personRepo.findAll()` first, and then subsequently for all method invocations. – Seelenvirtuose May 06 '15 at 15:55
  • I have the bad feeling that you want to test mockito instead of testing your code. What is the code of getByEmail()? What should it do? – JB Nizet May 06 '15 at 16:51

2 Answers2

10

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.

JohnK
  • 6,865
  • 8
  • 49
  • 75
Alex Wittig
  • 2,800
  • 1
  • 33
  • 42
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.

Alex Wittig
  • 2,800
  • 1
  • 33
  • 42
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251