如何为Java Stream编写Junit测试

7

我最近开始使用Java Stream编写一个用户服务,该服务返回一组用户流。利用该用户流,我可以处理其他逻辑。

以下是涉及到流的代码片段,它可以正常工作:

try (Stream<User> users = userService.getStream()) {
    users.forEach(user -> {
    });

但是当我开始编写 JUnit 时,它会出现以下错误消息。

java.lang.IllegalStateException: stream has already been operated upon or closed
    at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
    at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:647) 
    at com.test.UserService.sendBulkNotification(UserService.java:47)
    at com.test.UserServiceTest.sendNotificationTest(UserServiceTest.java:64) 

这是我的单元测试代码:

List<User> users = new ArrayList<>();
for(long i = 1; i <= 5; i++) {
    User user = new User();
    user.setId(i);
    users.add(user);
}

when(userService.getStream()).thenReturn(users.stream());
userService.sendNotification("user", 1, "test.com");

你能帮我编写关于流的测试用例/帮我解决这个问题吗?

1个回答

8
当您使用thenReturn(users.stream())时,您调用了users.stream()一次,并将该Stream对象交给Mockito运行时,每次触发when(...)时,它都会返回相同的实例。
由于Stream只能被消耗一次,任何次要触发都将失败。
您需要给Mockito一个可以在每次触发时生成新的Stream的工厂/供应商对象。Mockito称之为Answer,因此请改用thenAnswer(Answer<?> answer)
when(userService.getStream()).thenAnswer(invo -> users.stream());

你必须在lambda表达式中命名参数,但由于你没有使用它,所以可以任意命名。我使用了invo作为invocation的缩写,这是在Answer函数接口中声明为answer方法的参数名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接