使用Mockito 2.0.7模拟lambda表达式

时间:2015-05-06 15:35:29

标签: java unit-testing junit lambda mockito

我想模拟我的存储库中提供的查询,如下所示:

@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);
...

我的@Before方法如下所示:

@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);
}

可悲的是,当我运行测试时,我收到错误:

  

java.util.NoSuchElementException:没有值

当我双击错误时,它指向第一个lambda的.get()方法。

你们有没有成功嘲笑过一个lambda表达式,知道如何解决我的问题?

2 个答案:

答案 0 :(得分:8)

没有必要嘲笑这么深的电话。只需模拟personRepo.findAll()并让Streaming API正常工作:

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

然后而不是

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

只需将email个对象上的/ Person设置为预期值即可。

或者,考虑实施PersonRepo.findByEmail

答案 1 :(得分:2)

两件事:

With

首先,您尝试模拟五个不同方法调用的链。 Mockito并没有很好地处理这件事;虽然RETURNS_DEEP_STUBS answer(如果放在personRepo上)会保存并返回适用的存根对象,但每次调用Mockito.when(this.personRepo.findAll() .stream() .filter(p -> (p.getEmail().equals(Mockito.any(String.class)))) .findFirst() .get()) .thenReturn(this.personOut); 本身都会存在一个调用。

其次,Mockito匹配者不够灵活,无法深入调用电话;对when的调用应该只包含一个没有链接的方法调用,并且调用像when这样的Mockito匹配器stand in for exactly one of the arguments in that method。你拥有它的方式,你创建一个谓词any并在堆栈上留下一个匹配器以便以后解决问题。

使用Alex Wittig's answer来解决此问题,并注意在未来的问题中正确存根和使用匹配器。