'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 |