使用 Mockito 2.0.7 模拟 lambda 表达式
Use Mockito 2.0.7 to mock lambda expressions
我想像这样模拟存储库中提供的查询:
@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: No value present
当我双击错误时,它指向第一个 lambda 的 .get()
方法。
你们中有人成功模拟过 lambda 表达式并且知道我该如何解决我的问题吗?
没必要模拟这么深的调用。只需模拟 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))) )
只需 set/mock email
在您的 Person
对象上成为预期值。
或者,考虑实施 PersonRepo.findByEmail
。
两件事:
Mockito.when(this.personRepo.findAll()
.stream()
.filter(p -> (p.getEmail().equals(Mockito.any(String.class))))
.findFirst()
.get())
.thenReturn(this.personOut);
首先,您要模拟五个不同方法调用的链。 Mockito 处理得不是很好;尽管 RETURNS_DEEP_STUBS
answer(如果放在 personRepo 上)会保存并 return 在适用的情况下存根对象,但每次调用 when
本身都会存根一次调用。
其次,Mockito 匹配器不够灵活,无法在调用中深入工作;对 when
的调用应该只包含一个没有链接的方法调用,对 Mockito 匹配器(如 any
的调用应该 stand in for exactly one of the arguments in that method。按照你的方式,你正在创建一个谓词 p -> (p.getEmail().equals(null))
并在堆栈上留下一个匹配器以便稍后破坏。
使用来解决这个问题,并注意在以后的问题中正确地存根和使用匹配器。
我想像这样模拟存储库中提供的查询:
@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: No value present
当我双击错误时,它指向第一个 lambda 的 .get()
方法。
你们中有人成功模拟过 lambda 表达式并且知道我该如何解决我的问题吗?
没必要模拟这么深的调用。只需模拟 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))) )
只需 set/mock email
在您的 Person
对象上成为预期值。
或者,考虑实施 PersonRepo.findByEmail
。
两件事:
Mockito.when(this.personRepo.findAll()
.stream()
.filter(p -> (p.getEmail().equals(Mockito.any(String.class))))
.findFirst()
.get())
.thenReturn(this.personOut);
首先,您要模拟五个不同方法调用的链。 Mockito 处理得不是很好;尽管 RETURNS_DEEP_STUBS
answer(如果放在 personRepo 上)会保存并 return 在适用的情况下存根对象,但每次调用 when
本身都会存根一次调用。
其次,Mockito 匹配器不够灵活,无法在调用中深入工作;对 when
的调用应该只包含一个没有链接的方法调用,对 Mockito 匹配器(如 any
的调用应该 stand in for exactly one of the arguments in that method。按照你的方式,你正在创建一个谓词 p -> (p.getEmail().equals(null))
并在堆栈上留下一个匹配器以便稍后破坏。
使用