I am recently started using java stream and write a one User service, which returns a stream of users. Using that user stream, I process other logic.
Following is the piece of code that I am dealing with stream and it works fine
try (Stream<User> users = userService.getStream()) {
users.forEach(user -> {
});
But when I start writing Junit then it fails with following error message.
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)
Here is my unit test code:
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");
Could you please help me to write test case with stream/help me to fix this issue?
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()).
Unit testing APIs is an important part of API testing. Unit testing ensures that API components will function properly. In this article we will learn how to cover JUnit REST API testing with Spring Boot.
When you use thenReturn(users.stream())
, you call the users.stream()
once and hand that Stream
object over to the Mockito runtime, which will then return that same instance every time the when(...)
is triggered.
Since a Stream
can only be consumed once, any secondary triggers will fail.
You need to give Mockito a factory/supplier object that can produce a new Stream
every time the trigger fires. Mockito calls that an Answer
, so call thenAnswer(Answer<?> answer)
instead.
when(userService.getStream()).thenAnswer(invo -> users.stream());
You have to name the parameter in the lambda expression, but since you don't use it, you can call it anything. I used invo
as short for invocation
, the name of the parameter declared for the answer
method in the Answer
functional interface.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With