Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write Junit for Java Stream

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?

like image 530
Still Learning Avatar asked Feb 11 '20 03:02

Still Learning


People also ask

How do you write a stream JUnit?

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()).

Can JUnit be used for API testing?

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.


1 Answers

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.

like image 191
Andreas Avatar answered Nov 05 '22 22:11

Andreas