diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/NotConfiguredException.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/NotConfiguredException.java index a677491d25e04978252be8dd2cc48a70cf89bdd4..b75d2a066c979e91138bb0a4065ed7f9624aa456 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/NotConfiguredException.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/NotConfiguredException.java @@ -28,8 +28,11 @@ public class NotConfiguredException extends PostfachException { // NOSONAR private static final long serialVersionUID = 1L; public NotConfiguredException() { - super("Postfach is not completely configured. Sending and receiving of postfach mails is not possible.", - PostfachMessageCode.SERVER_CONNECTION_FAILED_MESSAGE_CODE); + this("Postfach is not completely configured. Sending and receiving of postfach mails is not possible."); + } + + public NotConfiguredException(String message) { + super(message, PostfachMessageCode.SERVICE_NOT_CONFIGURED); } } diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java index f2e5092837376b33c90d73b78b0fbf2ae963c85f..fba394eed05feba11bd9536693ec57cb64dbf203 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachMessageCode.java @@ -33,7 +33,9 @@ public enum PostfachMessageCode { PROCESS_FAILED_MESSAGE_CODE("postfachnachricht.server.processing_failed"), SERVER_CONNECTION_FAILED_MESSAGE_CODE("postfachnachricht.server.connection_failed"), SEND_SUCCESSFUL_MESSAGE_CODE("postfachnachricht.successful"), - SEND_FAILED_UNKNOWN_POSTFACH_ID_MESSAGE_CODE("postfachnachricht.server.unknown_postfach_id"); + SEND_FAILED_UNKNOWN_POSTFACH_ID_MESSAGE_CODE("postfachnachricht.server.unknown_postfach_id"), + SERVICE_NOT_CONFIGURED("postfachnachricht.server.service_not_configured"), + ; @Getter private String messageCode; diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java index 515ab8e5d5a73be9129ef25b924095aed635d235..b2bd6886410f8edcacc997cdfc246a7415989e9e 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachService.java @@ -23,11 +23,11 @@ package de.ozgcloud.nachrichten.postfach; import java.time.ZonedDateTime; +import java.util.Collection; import java.util.EnumSet; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.function.Predicate; import java.util.stream.Stream; import jakarta.annotation.PostConstruct; @@ -53,29 +53,25 @@ import lombok.extern.log4j.Log4j2; @Validated class PostfachService { - static final Predicate<PostfachNachricht> IS_MUK_ANSWER = nachricht -> StringUtils.isEmpty(nachricht.getVorgangId()) && StringUtils.isNotEmpty( - nachricht.getReferencedNachricht()); static final Set<ReplyOption> REPLY_POSSIBLE_OPTION = EnumSet.of(ReplyOption.POSSIBLE, ReplyOption.MANDATORY); private static final Set<String> POSTFACH_TYPES_WITH_ANTRAGSRAUM = Set.of("BAYERN_ID"); - @Autowired(required = false) - private PostfachRemoteService postfachRemoteService; @Autowired - private PostfachNachrichtMapper mapper; - + private Optional<Collection<PostfachRemoteService>> postfachRemoteServices; @Autowired - private PersistPostfachNachrichtService persistingService; - + private Optional<InfoManagerService> infomanagerService; @Autowired - private ApplicationEventPublisher publisher; - + private Optional<AntragraumService> antragraumService; + @Autowired + private PersistPostfachNachrichtService persistingService; @Autowired private CurrentUserService userService; @Autowired - private Optional<InfoManagerService> infomanagerService; + private PostfachNachrichtMapper mapper; + @Autowired - private Optional<AntragraumService> antragraumService; + private ApplicationEventPublisher publisher; @PostConstruct void logInit() { @@ -101,12 +97,16 @@ class PostfachService { .build(); } - void persistSentMail(@NonNull String userId, PostfachNachricht mail) { - persistMail(Optional.of(userId), mail.toBuilder() - .direction(Direction.OUT) - .createdAt(ZonedDateTime.now().withNano(0)).createdBy(userId) - .build()); + void persistSentMail(@NonNull String userId, PostfachNachricht postfachNachricht) { + persistMail(Optional.of(userId), buildOutgoingPostfachNachricht(userId, postfachNachricht)); + } + PostfachNachricht buildOutgoingPostfachNachricht(String userId, PostfachNachricht postfachNachricht) { + return postfachNachricht.toBuilder() + .direction(Direction.OUT) + .createdAt(ZonedDateTime.now().withNano(0)) + .createdBy(userId) + .build(); } public Optional<Map<String, Object>> findById(String nachrichtId) { @@ -118,17 +118,29 @@ class PostfachService { } public void fetchAndPersistReplies() { - ifPostfachConfigured(() -> postfachRemoteService.getAllMessages().forEach(this::persistReceivedMail)); + getPostfachRemoteServices().forEach(this::fetchAndPersistReplies); } - private void persistReceivedMail(PostfachNachricht nachricht) { - if (IS_MUK_ANSWER.test(nachricht)) { - nachricht = linkToVorgang(nachricht); + void fetchAndPersistReplies(PostfachRemoteService postfachRemoteService) { + try { + postfachRemoteService.getAllMessages().map(this::persistReceivedMail) + .forEach(postfachNachricht -> postfachRemoteService.deleteMessage(postfachNachricht.getMessageId())); + } catch (UnsupportedOperationException e) { + LOG.debug("Fetching of messages not supported for postfach type: {}", postfachRemoteService.getPostfachType()); } + } - persistMail(Optional.empty(), nachricht); + PostfachNachricht persistReceivedMail(PostfachNachricht postfachNachricht) { + if (isMukAnswer(postfachNachricht)) { + postfachNachricht = linkToVorgang(postfachNachricht); + } - postfachRemoteService.deleteMessage(nachricht.getMessageId()); + persistMail(Optional.empty(), postfachNachricht); + return postfachNachricht; + } + + boolean isMukAnswer(PostfachNachricht postfachNachricht) { + return StringUtils.isEmpty(postfachNachricht.getVorgangId()) && StringUtils.isNotEmpty(postfachNachricht.getReferencedNachricht()); } PostfachNachricht linkToVorgang(PostfachNachricht nachricht) { @@ -162,15 +174,17 @@ class PostfachService { } Optional<PostfachNachricht> processForAntragsraum(PostfachNachricht mail) { - if (isNotifyAntragsraum(mail.getReplyOption())) { + if (isNotifyAntragsraum(mail)) { infomanagerService.ifPresent(infoManager -> infoManager.notifyInfoManager(mail)); return adjustMail(mail); } return Optional.empty(); } - boolean isNotifyAntragsraum(ReplyOption replyOption) { - return REPLY_POSSIBLE_OPTION.contains(replyOption) && isPostfachWithAntragsraum(postfachRemoteService); + boolean isNotifyAntragsraum(PostfachNachricht postfachNachricht) { + return REPLY_POSSIBLE_OPTION.contains(postfachNachricht.getReplyOption()) + && findPostfachRemoteService(postfachNachricht.getPostfachAddress().getServiceKontoType()).filter(this::isPostfachWithAntragsraum) + .isPresent(); } Optional<PostfachNachricht> adjustMail(PostfachNachricht nachricht) { @@ -191,8 +205,12 @@ class PostfachService { return buildSendNachrichtResponse(false, e.getMessageCode()); } - void doSendMail(PostfachNachricht nachricht) { - ifPostfachConfigured(() -> postfachRemoteService.sendMessage(nachricht)); + void doSendMail(PostfachNachricht postfachNachricht) { + var postfachType = postfachNachricht.getPostfachAddress().getServiceKontoType(); + findPostfachRemoteService(postfachType).ifPresentOrElse(remoteService -> remoteService.sendMessage(postfachNachricht), + () -> { + throw new NotConfiguredException("Postfach of type %s not configured".formatted(postfachType)); + }); } private void publishMailSentEvent(String commandId) { @@ -213,16 +231,16 @@ class PostfachService { PostfachNachricht.FIELD_MESSAGE_CODE, sendResponse.getMessageCode().getMessageCode()); } - private void patchMail(String postfachMailId, Map<String, Object> propertyMap) { + void patchMail(String postfachMailId, Map<String, Object> propertyMap) { persistingService.patch(postfachMailId, propertyMap); } public boolean isPostfachConfigured() { - return postfachRemoteService != null; + return postfachRemoteServices.isPresent(); } public Stream<Postfach> getPostfachs() { - return isPostfachConfigured() ? Stream.of(buildPostfach(postfachRemoteService)) : Stream.empty(); + return postfachRemoteServices.stream().flatMap(Collection::stream).map(this::buildPostfach); } Postfach buildPostfach(PostfachRemoteService postfachRemoteService) { @@ -237,10 +255,16 @@ class PostfachService { return POSTFACH_TYPES_WITH_ANTRAGSRAUM.contains(postfachRemoteService.getPostfachType()) && infomanagerService.isPresent(); } - private void ifPostfachConfigured(Runnable block) { - if (!isPostfachConfigured()) { - throw new NotConfiguredException(); - } - block.run(); + Optional<PostfachRemoteService> findPostfachRemoteService(String postfachType) { + return getPostfachRemoteServices().filter(remoteService -> hasPostfachType(remoteService, postfachType)).findFirst(); + } + + boolean hasPostfachType(PostfachRemoteService postfachRemoteService, String postfachType) { + return StringUtils.equals(postfachRemoteService.getPostfachType(), postfachType); } + + Stream<PostfachRemoteService> getPostfachRemoteServices() { + return postfachRemoteServices.map(Collection::stream).orElseThrow(NotConfiguredException::new); + } + } \ No newline at end of file diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java index 566aff20bfc57f9dee6081f4544487b85e894217..09388bdb98b30d629601668af9747c7edb01110e 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/postfach/PostfachServiceTest.java @@ -22,13 +22,16 @@ */ package de.ozgcloud.nachrichten.postfach; -import static de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory.*; import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; +import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.stream.Stream; @@ -40,7 +43,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import org.mapstruct.factory.Mappers; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; @@ -52,8 +54,6 @@ import org.springframework.test.util.ReflectionTestUtils; import de.ozgcloud.nachrichten.antragraum.AntragraumService; import de.ozgcloud.nachrichten.info.InfoManagerService; -import de.ozgcloud.nachrichten.postfach.PostfachNachricht.Direction; -import de.ozgcloud.nachrichten.postfach.PostfachNachricht.ReplyOption; import de.ozgcloud.nachrichten.postfach.osi.MessageAttachmentService; import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory; import de.ozgcloud.nachrichten.postfach.osi.OsiPostfachServerProcessExceptionTestFactory; @@ -70,12 +70,14 @@ class PostfachServiceTest { @Spy @InjectMocks private PostfachService service; - @Mock - private PostfachRemoteService postfachRemoteService; + + private final PostfachRemoteService postfachRemoteService = mock(PostfachRemoteService.class); + @Spy + private Optional<Collection<PostfachRemoteService>> postfachRemoteServices = Optional.of(List.of(postfachRemoteService)); @Mock private PersistPostfachNachrichtService persistingService; - @Spy - private PostfachNachrichtMapper mapper = Mappers.getMapper(PostfachNachrichtMapper.class); + @Mock + private PostfachNachrichtMapper mapper; @Mock private MessageAttachmentService messageAttachmentService; @Mock @@ -129,200 +131,282 @@ class PostfachServiceTest { @Nested class TestSendMail { + @Mock + private PostfachNachricht postfachNachricht; + @Mock + private PostfachNachricht postfachNachrichtWithSentInformation; + @Mock + private SendPostfachNachrichtResponse sendResponse; + + @BeforeEach + void init() { + doNothing().when(service).persistSentMail(any(), any()); + doReturn(postfachNachrichtWithSentInformation).when(service).addMailSentInformation(any(), any()); + doReturn(sendResponse).when(service).handleSendMail(any(), any()); + } + @Test - void shouldCallDoSendMail() { - when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); - var mail = PostfachNachrichtTestFactory.create(); + void shouldCallHandleSendMail() { + service.sendMail(COMMAND_ID, USER_ID, postfachNachricht); + + verify(service).handleSendMail(COMMAND_ID, postfachNachricht); + } - service.sendMail(COMMAND_ID, USER_ID, mail); + @Test + void shouldCallAddMailSentInformation() { + service.sendMail(COMMAND_ID, USER_ID, postfachNachricht); - verify(service).doSendMail(mail); + verify(service).addMailSentInformation(postfachNachricht, sendResponse); } @Test void shouldCallPersistSentMail() { - when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); - var mail = PostfachNachrichtTestFactory.create(); - doReturn(mail).when(service).addMailSentInformation(any(PostfachNachricht.class), any(SendPostfachNachrichtResponse.class)); + service.sendMail(COMMAND_ID, USER_ID, postfachNachricht); - service.sendMail(COMMAND_ID, USER_ID, PostfachNachrichtTestFactory.create()); + verify(service).persistSentMail(USER_ID, postfachNachrichtWithSentInformation); + } + } + + @Nested + class TestAddMailSentInformation { + private static final PostfachNachricht POSTFACH_NACHRICHT = PostfachNachrichtTestFactory.createBuilder().sentAt(null).sentSuccessful(null) + .messageCode(null).build(); + private static final SendPostfachNachrichtResponse SEND_POSTFACH_NACHRICHT_RESPONSE = SendPostfachNachrichtResponseTestFactory.create(); - verify(service).persistSentMail(USER_ID, mail); + @Test + void shouldSetSentAt() { + var result = addMailSentInformation(); + + assertThat(result.getSentAt()).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS)); } @Test - void shouldAddMailSentInformation() { - var postfachMail = service.addMailSentInformation(PostfachNachrichtTestFactory.createBuilder().sentAt(null).sentSuccessful(null).build(), - SendPostfachNachrichtResponseTestFactory.create()); + void shouldSetSentSuccessful() { + var result = addMailSentInformation(); - assertThat(postfachMail.getSentAt()).isNotNull(); - assertThat(postfachMail.getSentSuccessful()).isEqualTo(SendPostfachNachrichtResponseTestFactory.SENT_SUCCESSFUL); - assertThat(postfachMail.getMessageCode()).isEqualTo(SendPostfachNachrichtResponseTestFactory.MESSAGE_CODE.getMessageCode()); + assertThat(result.getSentSuccessful()).isTrue(); } @Test - void shouldHandleSendMail() { - when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); - var mail = PostfachNachrichtTestFactory.create(); - service.sendMail(COMMAND_ID, USER_ID, mail); + void shouldSetMessageCode() { + var result = addMailSentInformation(); - verify(service).handleSendMail(COMMAND_ID, mail); + assertThat(result.getMessageCode()).isEqualTo(SendPostfachNachrichtResponseTestFactory.MESSAGE_CODE.getMessageCode()); } - @Nested - class TestPersistSentMail { + private PostfachNachricht addMailSentInformation() { + return service.addMailSentInformation(POSTFACH_NACHRICHT, SEND_POSTFACH_NACHRICHT_RESPONSE); + } + } - @Captor - private ArgumentCaptor<PostfachNachricht> mailCaptor; + @Nested + class TestPersistSentMail { - @Test - void shouldCallPersistingService() { - var mail = PostfachNachrichtTestFactory.create(); + private final PostfachNachricht outgoingPostfachNachricht = PostfachNachrichtTestFactory.create(); - service.persistSentMail(USER_ID, mail); + @BeforeEach + void init() { + doReturn(outgoingPostfachNachricht).when(service).buildOutgoingPostfachNachricht(any(), any()); + } - verify(persistingService).persistNachricht(any(), notNull()); - } + @Test + void shouldCallBuildOutgoingPostfachNachricht() { + var postfachNachricht = PostfachNachrichtTestFactory.create(); - @Test - void shouldSetDirectionToIN() { - service.persistSentMail(USER_ID, PostfachNachrichtTestFactory.createBuilder().direction(null).build()); + service.buildOutgoingPostfachNachricht(PostfachNachrichtTestFactory.CREATED_BY, postfachNachricht); - verify(persistingService).persistNachricht(any(), mailCaptor.capture()); - assertThat(mailCaptor.getValue().getDirection()).isEqualTo(Direction.OUT); - } + verify(service).buildOutgoingPostfachNachricht(PostfachNachrichtTestFactory.CREATED_BY, postfachNachricht); + } - @Test - void shouldSetCreatedAt() { - service.persistSentMail(USER_ID, PostfachNachrichtTestFactory.createBuilder().createdAt(null).build()); + @Test + void shouldCallPersistMail() { + service.persistSentMail(PostfachNachrichtTestFactory.CREATED_BY, PostfachNachrichtTestFactory.create()); - verify(persistingService).persistNachricht(any(), mailCaptor.capture()); - assertThat(mailCaptor.getValue().getCreatedAt()).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS)); - } + verify(service).persistMail(Optional.of(PostfachNachrichtTestFactory.CREATED_BY), outgoingPostfachNachricht); + } + } - @Test - void shouldSetCreatedBy() { - service.persistSentMail(USER_ID, PostfachNachrichtTestFactory.createBuilder().createdBy(null).build()); + @Nested + class TestBuildOutgoingPostfachNachricht { - verify(persistingService).persistNachricht(any(), mailCaptor.capture()); - assertThat(mailCaptor.getValue().getCreatedBy()).isEqualTo(USER_ID); - } + @Test + void shouldSetDirectionToOut() { + var result = buildOutgoingPostfachNachricht(); - @Test - void shouldSetUserId() { - var mail = PostfachNachrichtTestFactory.create(); + assertThat(result.getDirection()).isEqualTo(PostfachNachricht.Direction.OUT); + } - service.persistSentMail(USER_ID, mail); + @Test + void shouldSetCreatedAt() { + var result = buildOutgoingPostfachNachricht(); - verify(persistingService).persistNachricht(eq(Optional.of(USER_ID)), any()); - } + assertThat(result.getCreatedAt()).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS)); + } + + @Test + void shouldSetCreatedBy() { + var result = buildOutgoingPostfachNachricht(); + assertThat(result.getCreatedBy()).isEqualTo(PostfachNachrichtTestFactory.CREATED_BY); } - @Nested - class TestProcessForAntragsraum { + private PostfachNachricht buildOutgoingPostfachNachricht() { + var postfachNachricht = PostfachNachrichtTestFactory.createBuilder().direction(null).createdAt(null).createdBy(null).build(); + return service.buildOutgoingPostfachNachricht(PostfachNachrichtTestFactory.CREATED_BY, postfachNachricht); + } + } - @Mock - private PostfachNachricht modifiedMail; + @Nested + class TestProcessForAntragsraum { - @Test - void shouldReturnEmpty() { - doReturn(false).when(service).isPostfachWithAntragsraum(any()); + @Mock + private PostfachNachricht modifiedMail; + + @BeforeEach + void init() { + } - var result = service.processForAntragsraum(PostfachNachrichtTestFactory.create()); + @Test + void shouldReturnEmpty() { + doReturn(false).when(service).isNotifyAntragsraum(any()); - assertThat(result).isEmpty(); - } + var result = service.processForAntragsraum(PostfachNachrichtTestFactory.create()); - @Test - void shouldCallNotifyAntragsraum() { - doReturn(true).when(service).isPostfachWithAntragsraum(any()); - var mail = PostfachNachrichtTestFactory.create(); + assertThat(result).isEmpty(); + } - service.processForAntragsraum(mail); + @Test + void shouldCallNotifyAntragsraum() { + doReturn(true).when(service).isNotifyAntragsraum(any()); + var postfachNachricht = PostfachNachrichtTestFactory.create(); - verify(infomanagerService.get()).notifyInfoManager(mail); - } + service.processForAntragsraum(postfachNachricht); - @Test - void shouldReturnAdjustedMail() { - doReturn(true).when(service).isPostfachWithAntragsraum(any()); - doReturn(Optional.of(modifiedMail)).when(service).adjustMail(any()); + verify(infomanagerService.get()).notifyInfoManager(postfachNachricht); + } - var result = service.processForAntragsraum(PostfachNachrichtTestFactory.create()); + @Test + void shouldCallAdjustMail() { + doReturn(true).when(service).isNotifyAntragsraum(any()); + var postfachNachricht = PostfachNachrichtTestFactory.create(); - assertThat(result).contains(modifiedMail); - } + service.processForAntragsraum(postfachNachricht); - @DisplayName("Is notify antragsraum") - @Nested - class TestIsNotifyAntragsraum { + verify(service).adjustMail(postfachNachricht); + } - @DisplayName("should return true if") - @ParameterizedTest(name = "replyOption is {0}") - @EnumSource(value = ReplyOption.class, names = { "FORBIDDEN" }, mode = EnumSource.Mode.EXCLUDE) - void shouldConfirm(ReplyOption replyOption) { - doReturn(true).when(service).isPostfachWithAntragsraum(any()); + @Test + void shouldReturnAdjustedMail() { + doReturn(Optional.of(modifiedMail)).when(service).adjustMail(any()); + doReturn(true).when(service).isNotifyAntragsraum(any()); - var result = service.isNotifyAntragsraum(replyOption); + var result = service.processForAntragsraum(PostfachNachrichtTestFactory.create()); - assertThat(result).isTrue(); - } + assertThat(result).contains(modifiedMail); + } - @DisplayName("should return false if reply is forbidden") - @Test - void shouldDeclineIfForbidden() { - var result = service.isNotifyAntragsraum(ReplyOption.FORBIDDEN); + } - assertThat(result).isFalse(); - } + @DisplayName("Is notify antragsraum") + @Nested + class TestIsNotifyAntragsraum { - @DisplayName("should return false if antragsraum is not configured") - @Test - void shouldDeclineIfNotConfigured() { - doReturn(false).when(service).isPostfachWithAntragsraum(any()); + @Test + void shouldCallFindPostfachRemoteService() { + service.isNotifyAntragsraum(PostfachNachrichtTestFactory.create()); - var result = service.isNotifyAntragsraum(ReplyOption.POSSIBLE); + verify(service).findPostfachRemoteService(PostfachTestFactory.POSTFACH_TYPE); + } - assertThat(result).isFalse(); - } - } + @Test + void shouldCallIsPostfachWithAntragsraum() { + doReturn(true).when(service).isPostfachWithAntragsraum(any()); + doReturn(Optional.of(postfachRemoteService)).when(service).findPostfachRemoteService(any()); - @Nested - class TestAdjustMail { + service.isNotifyAntragsraum(PostfachNachrichtTestFactory.create()); - @Mock - private PostfachNachricht mail; + verify(service).isPostfachWithAntragsraum(postfachRemoteService); + } - private Optional<PostfachNachricht> adjustMail() { - return service.adjustMail(mail); - } + @DisplayName("should return true if postfach with antragraum configured and") + @ParameterizedTest(name = "replyOption is {0}") + @EnumSource(value = PostfachNachricht.ReplyOption.class, names = { "FORBIDDEN" }, mode = EnumSource.Mode.EXCLUDE) + void shouldConfirm(PostfachNachricht.ReplyOption replyOption) { + doReturn(Optional.of(postfachRemoteService)).when(service).findPostfachRemoteService(any()); + doReturn(true).when(service).isPostfachWithAntragsraum(any()); + var postfachNachricht = PostfachNachrichtTestFactory.createBuilder().replyOption(replyOption).build(); - @Nested - class TestReplaceBody { + var result = service.isNotifyAntragsraum(postfachNachricht); - @Test - void shouldReturnEmptyIfNoAntragsraum() { - ReflectionTestUtils.setField(service, "antragraumService", Optional.empty()); + assertThat(result).isTrue(); + } - var result = adjustMail(); + @DisplayName("should return false if postfach with antragraum configured and reply is forbidden") + @Test + void shouldDeclineIfForbidden() { + var postfachNachricht = PostfachNachrichtTestFactory.createBuilder().replyOption(PostfachNachricht.ReplyOption.FORBIDDEN).build(); - assertThat(result).isEmpty(); - } + var result = service.isNotifyAntragsraum(postfachNachricht); - @Test - void shouldAdjustMailBody() { - when(mail.toBuilder()).thenReturn(PostfachNachrichtTestFactory.createBuilder()); - var expectedMailBody = "Antragsraum Text"; - when(antragsraumService.get().getUserNotificationText()).thenReturn(expectedMailBody); + assertThat(result).isFalse(); + } - var result = adjustMail(); + @DisplayName("should return false if no postfach is configured") + @Test + void shouldDeclineIfNoPostfachRemoteService() { + doReturn(Optional.empty()).when(service).findPostfachRemoteService(any()); + var postfachNachricht = PostfachNachrichtTestFactory.createBuilder().replyOption(PostfachNachricht.ReplyOption.POSSIBLE).build(); - assertThat(result).isPresent().get().extracting(PostfachNachricht::getMailBody).isEqualTo(expectedMailBody); - } - } + var result = service.isNotifyAntragsraum(postfachNachricht); + + assertThat(result).isFalse(); + } + + @DisplayName("should return false if configured postfach without antragsraum") + @Test + void shouldDeclineIfNotConfigured() { + doReturn(Optional.of(postfachRemoteService)).when(service).findPostfachRemoteService(any()); + doReturn(false).when(service).isPostfachWithAntragsraum(any()); + var postfachNachricht = PostfachNachrichtTestFactory.createBuilder().replyOption(PostfachNachricht.ReplyOption.POSSIBLE).build(); + + var result = service.isNotifyAntragsraum(postfachNachricht); + + assertThat(result).isFalse(); + } + } + + @Nested + class TestAdjustMail { + + @Mock + private PostfachNachricht postfachNachricht; + + private Optional<PostfachNachricht> adjustMail() { + return service.adjustMail(postfachNachricht); + } + + @Nested + class TestReplaceBody { + + @Test + void shouldReturnEmptyIfNoAntragsraum() { + ReflectionTestUtils.setField(service, "antragraumService", Optional.empty()); + + var result = adjustMail(); + + assertThat(result).isEmpty(); } + @Test + void shouldAdjustMailBody() { + when(postfachNachricht.toBuilder()).thenReturn(PostfachNachrichtTestFactory.createBuilder()); + var expectedMailBody = "Antragsraum Text"; + when(antragsraumService.get().getUserNotificationText()).thenReturn(expectedMailBody); + + var result = adjustMail(); + + assertThat(result).isPresent().get().extracting(PostfachNachricht::getMailBody).isEqualTo(expectedMailBody); + } } } @@ -350,42 +434,83 @@ class PostfachServiceTest { } @Nested - class TestFetchAndPersistReplies { - - private static final PostfachNachricht nachricht = PostfachNachrichtTestFactory.create(); + class TestFetchAndPersistRepliesAllPostfachs { @BeforeEach void initTest() { - lenient().when(postfachRemoteService.getAllMessages()).thenReturn(Stream.of(nachricht)); + doReturn(Stream.of(postfachRemoteService)).when(service).getPostfachRemoteServices(); } @Test - void shouldCallGetAllMessages() { + void shouldCallGetPostfachRemoteServices() { service.fetchAndPersistReplies(); - verify(postfachRemoteService).getAllMessages(); + verify(service).getPostfachRemoteServices(); } @Test - void shouldCallPersistingService() { + void shouldCallFetchAndPersistReplies() { service.fetchAndPersistReplies(); - verify(persistingService).persistNachricht(eq(Optional.empty()), any()); + verify(service).fetchAndPersistReplies(postfachRemoteService); } + } - @Test - void shouldCallDelete() { - service.fetchAndPersistReplies(); + @Nested + class TestFetchAndPersistReplies { + + @Nested + class TestHappyPath { + + private final PostfachNachricht mappedPostfachNachricht = PostfachNachrichtTestFactory.create(); + + @Mock + private PostfachNachricht postfachNachricht; + + @BeforeEach + void init() { + when(postfachRemoteService.getAllMessages()).thenReturn(Stream.of(postfachNachricht)); + doReturn(mappedPostfachNachricht).when(service).persistReceivedMail(any()); + } + + @Test + void shouldCallGetAllMessages() { + service.fetchAndPersistReplies(postfachRemoteService); + + verify(postfachRemoteService).getAllMessages(); + } - verify(postfachRemoteService).deleteMessage(MessageTestFactory.MESSAGE_ID); + @Test + void shouldCallPersistReceivedMail() { + service.fetchAndPersistReplies(postfachRemoteService); + + verify(service).persistReceivedMail(postfachNachricht); + } + + @Test + void shouldCallDeleteMessage() { + service.fetchAndPersistReplies(postfachRemoteService); + + verify(postfachRemoteService).deleteMessage(MessageTestFactory.MESSAGE_ID); + } } - @Test - void shouldThrowNotConfiguredException() { - doReturn(false).when(service).isPostfachConfigured(); + @Nested + class TestWithUnsupportedOperationException { + + @Test + void shouldHandleWhenCallGetAllMessage() { + doThrow(new UnsupportedOperationException()).when(postfachRemoteService).getAllMessages(); + + assertDoesNotThrow(() -> service.fetchAndPersistReplies(postfachRemoteService)); + } + + @Test + void shouldHandleWhenCallDeleteMessage() { + doThrow(new UnsupportedOperationException()).when(postfachRemoteService).deleteMessage(anyString()); - assertThatExceptionOfType(NotConfiguredException.class).isThrownBy(() -> service.fetchAndPersistReplies()); - verify(postfachRemoteService, never()).getAllMessages(); + assertDoesNotThrow(() -> service.fetchAndPersistReplies(postfachRemoteService)); + } } } @@ -406,14 +531,20 @@ class PostfachServiceTest { @Nested class TestResendPostfachMail { - static final String COMMAND_ID = UUID.randomUUID().toString(); - static final PostfachNachricht mail = PostfachNachrichtTestFactory.create(); + private static final String COMMAND_ID = UUID.randomUUID().toString(); + private static final PostfachNachricht POSTFACH_NACHRICHT = PostfachNachrichtTestFactory.create(); + private static final Map<String, Object> RESEND_PATCH_MAP = Map.of("key", "value"); + + @Mock + private SendPostfachNachrichtResponse sendResponse; @BeforeEach void mockService() { when(persistingService.getById(anyString())).thenReturn(PostfachNachrichtTestFactory.asMap()); - doReturn(mail).when(mapper).fromMapToPostfachMail(anyMap()); - when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); + doReturn(POSTFACH_NACHRICHT).when(mapper).fromMapToPostfachMail(anyMap()); + doReturn(sendResponse).when(service).handleSendMail(any(), any()); + doReturn(RESEND_PATCH_MAP).when(service).createResendPatchMap(any()); + doNothing().when(service).patchMail(any(), any()); } @Test @@ -431,25 +562,26 @@ class PostfachServiceTest { } @Test - void shouldSendMail() { + void shouldCallHandleSentMail() { service.resendMail(COMMAND_ID, PostfachNachrichtTestFactory.ID); - verify(postfachRemoteService).sendMessage(any(PostfachNachricht.class)); + verify(service).handleSendMail(COMMAND_ID, POSTFACH_NACHRICHT); } @Test - void shouldPatchMail() { + void shouldCallCreateResendPatchMap() { service.resendMail(COMMAND_ID, PostfachNachrichtTestFactory.ID); - verify(persistingService).patch(anyString(), anyMap()); + verify(service).createResendPatchMap(sendResponse); } @Test - void shouldHandleSentMail() { + void shouldCallPatchMail() { service.resendMail(COMMAND_ID, PostfachNachrichtTestFactory.ID); - verify(service).handleSendMail(COMMAND_ID, mail); + verify(service).patchMail(PostfachNachrichtTestFactory.ID, RESEND_PATCH_MAP); } + } @Nested @@ -505,6 +637,11 @@ class PostfachServiceTest { @Mock private PostfachNachricht modifiedMail; + @BeforeEach + void init() { + doNothing().when(service).doSendMail(any()); + } + @Test void shouldDoSendMail() { when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); @@ -667,26 +804,35 @@ class PostfachServiceTest { @Nested class TestDoSendMail { + + @Mock + private PostfachRemoteService postfachRemoteService; + @Test - void shouldCallPostfachRemoteService() { + void shouldCallFindPostfachRemoteService() { + doReturn(Optional.of(postfachRemoteService)).when(service).findPostfachRemoteService(any()); + service.doSendMail(PostfachNachrichtTestFactory.create()); - verify(postfachRemoteService).sendMessage(any()); + verify(service).findPostfachRemoteService(PostfachTestFactory.POSTFACH_TYPE); } - @Nested - class WithoutRemoteService { - @InjectMocks - private PostfachService service; + @Test + void shouldCallSendMessage() { + doReturn(Optional.of(postfachRemoteService)).when(service).findPostfachRemoteService(any()); + var postfachNachricht = PostfachNachrichtTestFactory.create(); - @Test - void shouldThrowNotConfiguredException() { - var nachricht = PostfachNachrichtTestFactory.create(); + service.doSendMail(postfachNachricht); - assertThatExceptionOfType(NotConfiguredException.class).isThrownBy(() -> service.doSendMail(nachricht)); + verify(postfachRemoteService).sendMessage(postfachNachricht); + } - verify(postfachRemoteService, never()).sendMessage(any()); - } + @Test + void shouldThrowNotConfiguredException() { + doReturn(Optional.empty()).when(service).findPostfachRemoteService(any()); + var postfachNachricht = PostfachNachrichtTestFactory.create(); + + assertThrows(NotConfiguredException.class, () -> service.doSendMail(postfachNachricht)); } } @@ -695,8 +841,10 @@ class PostfachServiceTest { class TestIsPostfachConfigured { @Test - void shouldReturnTrue() { - assertThat(service.isPostfachConfigured()).isTrue(); + void shouldCallIsPresent() { + service.isPostfachConfigured(); + + verify(postfachRemoteServices).isPresent(); } } @@ -705,129 +853,221 @@ class PostfachServiceTest { private final Postfach postfach = PostfachTestFactory.create(); + @BeforeEach + void init() { + doReturn(postfach).when(service).buildPostfach(any()); + } + @Test void shouldCallBuildPostfach() { when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); - service.getPostfachs(); + getPostfachs(); verify(service).buildPostfach(postfachRemoteService); } @Test void shouldReturnPostfachs() { - doReturn(postfach).when(service).buildPostfach(any()); - - var result = service.getPostfachs(); + var result = getPostfachs(); assertThat(result).containsOnly(postfach); } + private List<Postfach> getPostfachs() { + return service.getPostfachs().toList(); + } + } + + @Nested + class TestBuildPostfach { + + @Test + void shouldSetPostfachType() { + when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); + + var result = service.buildPostfach(postfachRemoteService); + + assertThat(result.getType()).isEqualTo(PostfachTestFactory.POSTFACH_TYPE); + } + @Test - void shouldReturnEmptyStream() { - doReturn(false).when(service).isPostfachConfigured(); + void shouldSetIsReplyAllowed() { + doReturn(true).when(service).isReplyAllowed(any()); - var result = service.getPostfachs(); + var result = service.buildPostfach(postfachRemoteService); - assertThat(result).isEmpty(); + assertThat(result.isReplyAllowed()).isTrue(); + } + } + + @Nested + class TestIsReplyAllowed { + + @Test + void shouldAllowWithAntragsraum() { + doReturn(true).when(service).isPostfachWithAntragsraum(postfachRemoteService); + + var result = service.isReplyAllowed(postfachRemoteService); + + assertThat(result).isTrue(); + } + + @Test + void shouldAllowWithPostfach() { + doReturn(false).when(service).isPostfachWithAntragsraum(postfachRemoteService); + when(postfachRemoteService.isReplyAllowed()).thenReturn(true); + + var result = service.isReplyAllowed(postfachRemoteService); + + assertThat(result).isTrue(); + } + + @Test + void shouldNotAllow() { + doReturn(false).when(service).isPostfachWithAntragsraum(postfachRemoteService); + + var result = service.isReplyAllowed(postfachRemoteService); + + assertThat(result).isFalse(); + } + } + + @Nested + class TestPersistReceivedMail { + + @Test + void shouldCallIsMukAnswer() { + var postfachNachricht = PostfachNachrichtTestFactory.create(); + + service.persistReceivedMail(postfachNachricht); + + verify(service).isMukAnswer(postfachNachricht); } @Nested - class TestBuildPostfach { + class TestPostfachNachricht { + + @BeforeEach + void init() { + doReturn(false).when(service).isMukAnswer(any()); + } @Test - void shouldSetPostfachType() { - when(postfachRemoteService.getPostfachType()).thenReturn(PostfachTestFactory.POSTFACH_TYPE); + void shouldCallPersistMail() { + var postfachNachricht = PostfachNachrichtTestFactory.create(); - var result = service.buildPostfach(postfachRemoteService); + service.persistReceivedMail(postfachNachricht); - assertThat(result.getType()).isEqualTo(PostfachTestFactory.POSTFACH_TYPE); + verify(service).persistMail(Optional.empty(), postfachNachricht); } @Test - void shouldSetIsReplyAllowed() { - doReturn(true).when(service).isReplyAllowed(any()); + void shouldReturnPostfachNachricht() { + var postfachNachricht = PostfachNachrichtTestFactory.create(); - var result = service.buildPostfach(postfachRemoteService); + var result = service.persistReceivedMail(postfachNachricht); - assertThat(result.isReplyAllowed()).isTrue(); + assertThat(result).isSameAs(postfachNachricht); } } @Nested - class TestIsReplyAllowed { - - @Test - void shouldAllowWithAntragsraum() { - doReturn(true).when(service).isPostfachWithAntragsraum(postfachRemoteService); + class TestMukAnswer { - var result = service.isReplyAllowed(postfachRemoteService); + private final PostfachNachricht postfachNachrichtWithVorgang = PostfachNachrichtTestFactory.create(); - assertThat(result).isTrue(); + @BeforeEach + void init() { + doReturn(true).when(service).isMukAnswer(any()); + doReturn(postfachNachrichtWithVorgang).when(service).linkToVorgang(any()); } @Test - void shouldAllowWithPostfach() { - doReturn(false).when(service).isPostfachWithAntragsraum(postfachRemoteService); - when(postfachRemoteService.isReplyAllowed()).thenReturn(true); + void shouldCallLinkToVorgang() { + var postfachNachricht = PostfachNachrichtTestFactory.create(); - var result = service.isReplyAllowed(postfachRemoteService); + service.persistReceivedMail(postfachNachricht); - assertThat(result).isTrue(); + verify(service).linkToVorgang(postfachNachricht); } @Test - void shouldNotAllow() { - doReturn(false).when(service).isPostfachWithAntragsraum(postfachRemoteService); + void shouldCallPersistMail() { + service.persistReceivedMail(PostfachNachrichtTestFactory.create()); + + verify(service).persistMail(Optional.empty(), postfachNachrichtWithVorgang); + } - var result = service.isReplyAllowed(postfachRemoteService); + @Test + void shouldReturnUpdatedPostfachNachricht() { + var result = service.persistReceivedMail(PostfachNachrichtTestFactory.create()); - assertThat(result).isFalse(); + assertThat(result).isSameAs(postfachNachrichtWithVorgang); } } + } @Nested class TestSavingMukAnswer { + private final String refId = ObjectId.get().toHexString(); private final PostfachNachricht answer = PostfachNachrichtTestFactory.createBuilder().vorgangId(null).referencedNachricht(refId).build(); @Test void shouldIdentifyAsAnswer() { - var isMukAnswer = PostfachService.IS_MUK_ANSWER.test(answer); + var isMukAnswer = service.isMukAnswer(answer); assertThat(isMukAnswer).isTrue(); } @Test void shouldNotIdentifyAsAnswer() { - var isMukAnswer = PostfachService.IS_MUK_ANSWER.test(PostfachNachrichtTestFactory.create()); + var isMukAnswer = service.isMukAnswer(PostfachNachrichtTestFactory.create()); assertThat(isMukAnswer).isFalse(); } - @Nested - class TestLinkingMukAnswerToVorgang { + } - @Test - void shouldLoadPersistedNachricht() { - when(service.isPostfachConfigured()).thenReturn(Boolean.TRUE); - when(postfachRemoteService.getAllMessages()).thenReturn(Stream.of(answer)); - when(persistingService.getById(anyString())).thenReturn(PostfachNachrichtTestFactory.asMap()); + @Nested + class TestLinkToVorgang { - service.fetchAndPersistReplies(); + private static final String REFERENCE_ID = "reference-id"; + private static final PostfachNachricht POSTFACH_NACHRICHT = PostfachNachrichtTestFactory.createBuilder().vorgangId(null) + .referencedNachricht(REFERENCE_ID).build(); + private static final PostfachNachricht PERSISTED_NACHRICHT = PostfachNachrichtTestFactory.create(); + private static final Map<String, Object> POSTFACH_NACHRICHT_MAP = PostfachNachrichtTestFactory.asMap(); - verify(persistingService).getById(any()); - } + @BeforeEach + void init() { + when(mapper.fromMapToPostfachMail(anyMap())).thenReturn(PERSISTED_NACHRICHT); + when(persistingService.getById(anyString())).thenReturn(POSTFACH_NACHRICHT_MAP); + } - @Test - void shouldSetVorgangId() { - when(persistingService.getById(anyString())).thenReturn(PostfachNachrichtTestFactory.asMap()); + @Test + void shouldLoadPersistedNachricht() { + service.linkToVorgang(POSTFACH_NACHRICHT); - var linkedNachricht = service.linkToVorgang(answer); + verify(persistingService).getById(REFERENCE_ID); + } - assertThat(linkedNachricht.getVorgangId()).isEqualTo(VORGANG_ID); - } + @Test + void shouldCallFromMapToPostfachMail() { + service.linkToVorgang(POSTFACH_NACHRICHT); + + verify(mapper).fromMapToPostfachMail(POSTFACH_NACHRICHT_MAP); + } + + @Test + void shouldSetVorgangId() { + when(persistingService.getById(anyString())).thenReturn(PostfachNachrichtTestFactory.asMap()); + + var result = service.linkToVorgang(POSTFACH_NACHRICHT); + + assertThat(result.getVorgangId()).isEqualTo(MessageTestFactory.VORGANG_ID); } } + } \ No newline at end of file