Как написать Junit для Java Stream - PullRequest
6 голосов
/ 11 февраля 2020

Я недавно начал использовать поток java и написать сервис с одним пользователем, который возвращает поток пользователей. Используя этот пользовательский поток, я обрабатываю другие логи c.

Ниже приведен фрагмент кода, с которым я имею дело в потоке, и он отлично работает

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 Ответ

7 голосов
/ 11 февраля 2020

Когда вы используете thenReturn(users.stream()), вы вызываете users.stream() один раз и передаете этот объект Stream во время выполнения Mockito, которое будет возвращать тот же самый экземпляр каждый раз при запуске when(...).

Поскольку Stream может использоваться только один раз, любые вторичные триггеры не будут работать.

Вам необходимо предоставить Mockito объект фабрики / поставщика, который может производить новый Stream при каждом срабатывании триггера. Mockito называет это Answer, поэтому вместо этого назовите thenAnswer(Answer<?> answer).

when(userService.getStream()).thenAnswer(invo -> users.stream());

Параметр должен быть назван в лямбда-выражении, но так как вы его не используете, Вы можете назвать это как угодно. Я использовал invo как сокращение от invocation, имя параметра, объявленного для метода answer в функциональном интерфейсе Answer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...