Skip to content
Snippets Groups Projects
Commit f971ab21 authored by OZGCloud's avatar OZGCloud
Browse files

OZG-7038 move xta classes to common package; combine xta service class

parent a4e740af
No related branches found
No related tags found
1 merge request!3Ozg 7038 evaluation dms quittung
Showing
with 346 additions and 366 deletions
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import java.io.IOException; import java.io.IOException;
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
......
package de.ozgcloud.archive.common.xta; package de.ozgcloud.archive.common.xta;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import de.ozgcloud.archive.common.command.ArchiveManagerCommand;
import de.ozgcloud.archive.common.command.CommandOrder;
import de.ozgcloud.archive.common.command.CommandService;
import de.ozgcloud.archive.common.xta.XtaImportConfirmationHandler.XtaAbgabeHandler;
import de.ozgcloud.command.Command;
import de.ozgcloud.command.CommandExecutedEvent;
import de.ozgcloud.command.CommandFailedEvent;
import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.xta.client.XtaClient; import de.ozgcloud.xta.client.XtaClient;
import de.ozgcloud.xta.client.exception.XtaClientException; import de.ozgcloud.xta.client.exception.XtaClientException;
...@@ -11,13 +21,20 @@ import de.ozgcloud.xta.client.model.XtaFile; ...@@ -11,13 +21,20 @@ import de.ozgcloud.xta.client.model.XtaFile;
import de.ozgcloud.xta.client.model.XtaMessage; import de.ozgcloud.xta.client.model.XtaMessage;
import de.ozgcloud.xta.client.xdomea.XdomeaXtaMessageCreator; import de.ozgcloud.xta.client.xdomea.XdomeaXtaMessageCreator;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@RequiredArgsConstructor @RequiredArgsConstructor
@Service @Service
public class XtaService { public class XtaService {
private static final String XTA_CLIENT_IS_NOT_CONFIGURED_MESSAGE = "XtaClient is not configured! Cannot send message to DMS."; private static final String XTA_CLIENT_IS_NOT_CONFIGURED_MESSAGE = "XtaClient is not configured! Cannot send message to DMS.";
private final Optional<XtaClient> xtaClient; private final Optional<XtaClient> xtaClient;
private final XtaFileHelper xtaFileHelper;
private final CommandService commandService;
private final ApplicationEventPublisher eventPublisher;
public void sendXdomeaFile(XtaFile xdomeaFile) { public void sendXdomeaFile(XtaFile xdomeaFile) {
try { try {
...@@ -38,4 +55,56 @@ public class XtaService { ...@@ -38,4 +55,56 @@ public class XtaService {
XtaClient getXtaClient() { XtaClient getXtaClient() {
return xtaClient.orElseThrow(() -> new TechnicalException(XTA_CLIENT_IS_NOT_CONFIGURED_MESSAGE)); return xtaClient.orElseThrow(() -> new TechnicalException(XTA_CLIENT_IS_NOT_CONFIGURED_MESSAGE));
} }
public void fetchMessages() {
try {
getXtaClient().fetchMessages(this::consumeMessage);
} catch (XtaClientException e) {
throw new TechnicalException("Error fetching xta messages.", e);
}
}
void consumeMessage(XtaMessage message) {
if (isImportConfirmation(message.messageFile())) {
xtaFileHelper.initImportConfirmationHandler(message.messageFile()).getAbgaben().forEach(this::handleAbgabe);
}
}
boolean isImportConfirmation(XtaFile xtaFile) {
return XtaFileXmlUtils.isType(xtaFile, XtaFileType.IMPORT_CONFIRMATION);
}
void handleAbgabe(XtaAbgabeHandler abgabeHandler) {
var vorgangId = abgabeHandler.getVorgangId();
var pendingCommands = findPendingArchiveVorgangCommands(vorgangId);
if (CollectionUtils.isNotEmpty(pendingCommands)) {
evaluateAbgabe(abgabeHandler, pendingCommands);
} else {
LOG.warn("No pending archive command found for vorgang: %s.", vorgangId);
}
}
private List<ArchiveManagerCommand> findPendingArchiveVorgangCommands(String vorgangId) {
return commandService.findPending(vorgangId, CommandOrder.ARCHIVE_VORGANG).toList();
}
void evaluateAbgabe(XtaAbgabeHandler abgabeHandler, List<ArchiveManagerCommand> pendingCommands) {
if (pendingCommands.size() > 1) {
LOG.warn("Multiple pending commands found for vorgang: %s.", abgabeHandler.getVorgangId());
}
if (abgabeHandler.isSuccessfullyDone()) {
pendingCommands.forEach(this::publishCommandExecutedEvent);
} else {
pendingCommands.forEach(command -> publishCommandFailedEvent(abgabeHandler, command));
}
}
void publishCommandExecutedEvent(Command pendingCommand) {
eventPublisher.publishEvent(new CommandExecutedEvent(pendingCommand));
}
void publishCommandFailedEvent(XtaAbgabeHandler contentHandler, Command pendingCommand) {
eventPublisher.publishEvent(new CommandFailedEvent(pendingCommand.getId(), contentHandler.getFehlermeldung()));
}
} }
package de.ozgcloud.archive.xta;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import de.ozgcloud.archive.common.command.ArchiveManagerCommand;
import de.ozgcloud.archive.common.command.CommandOrder;
import de.ozgcloud.archive.common.command.CommandService;
import de.ozgcloud.archive.xta.XtaImportConfirmationHandler.XtaAbgabeHandler;
import de.ozgcloud.command.Command;
import de.ozgcloud.command.CommandExecutedEvent;
import de.ozgcloud.command.CommandFailedEvent;
import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.xta.client.XtaClient;
import de.ozgcloud.xta.client.exception.XtaClientException;
import de.ozgcloud.xta.client.model.XtaFile;
import de.ozgcloud.xta.client.model.XtaMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
@Log4j2
@RequiredArgsConstructor
@Service
class XtaService {
private final XtaClient client;
private final XtaFileHelper xtaFileHelper;
private final CommandService commandService;
private final ApplicationEventPublisher eventPublisher;
public void fetchMessages() {
try {
client.fetchMessages(this::consumeMessage);
} catch (XtaClientException e) {
throw new TechnicalException("Error fetching xta messages.", e);
}
}
void consumeMessage(XtaMessage message) {
if (isImportConfirmation(message.messageFile())) {
xtaFileHelper.initImportConfirmationHandler(message.messageFile()).getAbgaben().forEach(this::handleAbgabe);
}
}
boolean isImportConfirmation(XtaFile xtaFile) {
return XtaFileXmlUtils.isType(xtaFile, XtaFileType.IMPORT_CONFIRMATION);
}
void handleAbgabe(XtaAbgabeHandler abgabeHandler) {
var vorgangId = abgabeHandler.getVorgangId();
var pendingCommands = findPendingArchiveVorgangCommands(vorgangId);
if (CollectionUtils.isNotEmpty(pendingCommands)) {
evaluateAbgabe(abgabeHandler, pendingCommands);
} else {
LOG.warn("No pending archive command found for vorgang: %s.", vorgangId);
}
}
private List<ArchiveManagerCommand> findPendingArchiveVorgangCommands(String vorgangId) {
return commandService.findPending(vorgangId, CommandOrder.ARCHIVE_VORGANG).toList();
}
void evaluateAbgabe(XtaAbgabeHandler abgabeHandler, List<ArchiveManagerCommand> pendingCommands) {
if (pendingCommands.size() > 1) {
LOG.warn("Multiple pending commands found for vorgang: %s.", abgabeHandler.getVorgangId());
}
if (abgabeHandler.isSuccessfullyDone()) {
pendingCommands.forEach(this::publishCommandExecutedEvent);
} else {
pendingCommands.forEach(command -> publishCommandFailedEvent(abgabeHandler, command));
}
}
void publishCommandExecutedEvent(Command pendingCommand) {
eventPublisher.publishEvent(new CommandExecutedEvent(pendingCommand));
}
void publishCommandFailedEvent(XtaAbgabeHandler contentHandler, Command pendingCommand) {
eventPublisher.publishEvent(new CommandFailedEvent(pendingCommand.getId(), contentHandler.getFehlermeldung()));
}
}
\ No newline at end of file
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import de.ozgcloud.archive.common.xta.XtaFileXmlUtils;
import de.xoev.xdomea.AbgabeImportBestaetigen0402; import de.xoev.xdomea.AbgabeImportBestaetigen0402;
import lombok.SneakyThrows; import lombok.SneakyThrows;
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
...@@ -7,6 +7,9 @@ import org.junit.jupiter.api.Nested; ...@@ -7,6 +7,9 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import de.ozgcloud.archive.common.xta.XtaFileHelper;
import de.ozgcloud.archive.common.xta.XtaImportConfirmationHandler;
class XtaFileHelperTest { class XtaFileHelperTest {
@InjectMocks @InjectMocks
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import jakarta.activation.DataHandler; import jakarta.activation.DataHandler;
import jakarta.activation.FileDataSource; import jakarta.activation.FileDataSource;
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*; import static org.mockito.ArgumentMatchers.*;
...@@ -11,6 +11,8 @@ import org.junit.jupiter.api.Test; ...@@ -11,6 +11,8 @@ import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic; import org.mockito.MockedStatic;
import org.mockito.Mockito; import org.mockito.Mockito;
import de.ozgcloud.archive.common.xta.XtaFileType;
import de.ozgcloud.archive.common.xta.XtaFileXmlUtils;
import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.common.errorhandling.TechnicalException;
class XtaFileXmlUtilsTest { class XtaFileXmlUtilsTest {
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*; import static org.mockito.ArgumentMatchers.*;
...@@ -11,7 +11,9 @@ import org.junit.jupiter.api.Test; ...@@ -11,7 +11,9 @@ import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic; import org.mockito.MockedStatic;
import org.mockito.Mockito; import org.mockito.Mockito;
import de.ozgcloud.archive.xta.XtaImportConfirmationHandler.XtaAbgabeHandler; import de.ozgcloud.archive.common.xta.XtaFileXmlUtils;
import de.ozgcloud.archive.common.xta.XtaImportConfirmationHandler;
import de.ozgcloud.archive.common.xta.XtaImportConfirmationHandler.XtaAbgabeHandler;
import de.ozgcloud.xta.client.model.XtaFile; import de.ozgcloud.xta.client.model.XtaFile;
import de.xoev.xdomea.AbgabeImportBestaetigen0402; import de.xoev.xdomea.AbgabeImportBestaetigen0402;
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
...@@ -8,6 +8,9 @@ import org.mockito.InjectMocks; ...@@ -8,6 +8,9 @@ import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Spy; import org.mockito.Spy;
import de.ozgcloud.archive.common.xta.XtaMessageScheduler;
import de.ozgcloud.archive.common.xta.XtaService;
class XtaMessageSchedulerTest { class XtaMessageSchedulerTest {
@Spy @Spy
......
package de.ozgcloud.archive.xta; package de.ozgcloud.archive.common.xta;
import de.ozgcloud.xta.client.model.XtaFile; import de.ozgcloud.xta.client.model.XtaFile;
import de.ozgcloud.xta.client.model.XtaMessage; import de.ozgcloud.xta.client.model.XtaMessage;
......
...@@ -5,18 +5,32 @@ import static org.junit.jupiter.api.Assertions.*; ...@@ -5,18 +5,32 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*; import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockedStatic; import org.mockito.MockedStatic;
import org.mockito.Spy; import org.mockito.Spy;
import org.springframework.context.ApplicationEventPublisher;
import de.ozgcloud.archive.common.command.ArchiveManagerCommand;
import de.ozgcloud.archive.common.command.CommandOrder;
import de.ozgcloud.archive.common.command.CommandService;
import de.ozgcloud.archive.common.command.CommandTestFactory;
import de.ozgcloud.archive.common.xta.XtaImportConfirmationHandler.XtaAbgabeHandler;
import de.ozgcloud.archive.vorgang.VorgangWithEingangTestFactory;
import de.ozgcloud.archive.vorgang.XdomeaXtaFileTestFactory; import de.ozgcloud.archive.vorgang.XdomeaXtaFileTestFactory;
import de.ozgcloud.command.CommandExecutedEvent;
import de.ozgcloud.command.CommandFailedEvent;
import de.ozgcloud.common.errorhandling.TechnicalException; import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.xta.client.XtaClient; import de.ozgcloud.xta.client.XtaClient;
import de.ozgcloud.xta.client.exception.XtaClientException; import de.ozgcloud.xta.client.exception.XtaClientException;
...@@ -34,6 +48,13 @@ class XtaServiceTest { ...@@ -34,6 +48,13 @@ class XtaServiceTest {
@Mock @Mock
private XtaClient xtaClient; private XtaClient xtaClient;
@Mock
private CommandService commandService;
@Mock
private ApplicationEventPublisher eventPublisher;
@Mock
private XtaFileHelper xtaFileHelper;
@Nested @Nested
class TestSendXdomeaFile { class TestSendXdomeaFile {
...@@ -148,12 +169,21 @@ class XtaServiceTest { ...@@ -148,12 +169,21 @@ class XtaServiceTest {
private XtaService xtaService; private XtaService xtaService;
@Mock
private XtaFileHelper xtaFileHelper;
@Mock
private CommandService commandService;
@Mock
private ApplicationEventPublisher eventPublisher;
@Nested @Nested
class TestOnConfiguredXtaClient { class TestOnConfiguredXtaClient {
@BeforeEach @BeforeEach
void givenXtaClientConfigured() { void givenXtaClientConfigured() {
xtaService = spy(new XtaService(Optional.of(xtaClient))); xtaService = spy(new XtaService(Optional.of(xtaClient), xtaFileHelper, commandService, eventPublisher));
} }
@Test @Test
...@@ -170,7 +200,7 @@ class XtaServiceTest { ...@@ -170,7 +200,7 @@ class XtaServiceTest {
@BeforeEach @BeforeEach
void givenXtaClientNotConfigured() { void givenXtaClientNotConfigured() {
xtaService = spy(new XtaService(Optional.empty())); xtaService = spy(new XtaService(Optional.empty(), xtaFileHelper, commandService, eventPublisher));
} }
@Test @Test
...@@ -183,4 +213,224 @@ class XtaServiceTest { ...@@ -183,4 +213,224 @@ class XtaServiceTest {
return xtaService.getXtaClient(); return xtaService.getXtaClient();
} }
} }
@DisplayName("Fetch messages")
@Nested
class TestFetchMessages {
@BeforeEach
void mock() {
doReturn(xtaClient).when(service).getXtaClient();
}
@SneakyThrows
@Test
void shouldCallClient() {
service.fetchMessages();
verify(xtaClient).fetchMessages(any());
}
@SneakyThrows
@Test
void shouldThrowException() {
when(xtaClient.fetchMessages(any())).thenThrow(new XtaClientException("error-message"));
assertThatThrownBy(() -> service.fetchMessages()).isInstanceOf(TechnicalException.class);
}
}
@DisplayName("Consume message")
@Nested
class TestConsumeMessage {
@Mock
private XtaImportConfirmationHandler xtaFileContentHandler;
private final XtaMessage xtaMessage = XtaMessageTestFactory.create();
@Test
void shouldCallIsImportConfirmation() {
service.consumeMessage(xtaMessage);
verify(service).isImportConfirmation(XtaMessageTestFactory.MESSAGE_FILE);
}
@DisplayName("on import confirmation")
@Nested
class TestOnImportConfirmation {
@Mock
private XtaAbgabeHandler abgabeHandler;
@BeforeEach
void mock() {
doReturn(true).when(service).isImportConfirmation(any());
when(xtaFileHelper.initImportConfirmationHandler(any())).thenReturn(xtaFileContentHandler);
when(xtaFileContentHandler.getAbgaben()).thenReturn(Stream.of(abgabeHandler, abgabeHandler));
doNothing().when(service).handleAbgabe(any());
}
@Test
void shouldInitContentHandler() {
service.consumeMessage(xtaMessage);
verify(xtaFileHelper).initImportConfirmationHandler(XtaMessageTestFactory.MESSAGE_FILE);
}
@DisplayName("should handle import confirmation if type from document is matching")
@Test
void shouldCallHandleAbgabe() {
service.consumeMessage(xtaMessage);
verify(service, times(2)).handleAbgabe(abgabeHandler);
}
}
@DisplayName("should not handle message if its not an import confirmation")
@Test
void shouldNotProceed() {
doReturn(false).when(service).isImportConfirmation(any());
service.consumeMessage(xtaMessage);
verify(service, never()).handleAbgabe(any());
verify(xtaFileHelper, never()).initImportConfirmationHandler(any());
}
}
@DisplayName("Handle abgabe")
@Nested
class TestHandleAbgabe {
@Mock
private XtaAbgabeHandler abgabeHandler;
@BeforeEach
void mock() {
when(abgabeHandler.getVorgangId()).thenReturn(VorgangWithEingangTestFactory.ID);
when(commandService.findPending(any(), any())).thenReturn(Stream.empty());
}
@Test
void shouldGetVorgangId() {
handleImportConfirmation();
verify(abgabeHandler).getVorgangId();
}
@Test
void shouldCallCommandService() {
handleImportConfirmation();
verify(commandService).findPending(VorgangWithEingangTestFactory.ID, CommandOrder.ARCHIVE_VORGANG);
}
@DisplayName("on existing pending commands")
@Nested
class TestOnExistingPendingCommands {
private final ArchiveManagerCommand command = CommandTestFactory.create();
private final List<ArchiveManagerCommand> commands = List.of(command);
@BeforeEach
void mock() {
when(commandService.findPending(any(), any())).thenReturn(commands.stream());
doNothing().when(service).evaluateAbgabe(any(), any());
}
@Test
void shouldCallEvaluateConfirmation() {
handleImportConfirmation();
verify(service).evaluateAbgabe(abgabeHandler, commands);
}
}
@Test
void shouldNotCallEvaluateImportConfirmationOnEmptyList() {
handleImportConfirmation();
verify(service, never()).evaluateAbgabe(any(), any());
}
private void handleImportConfirmation() {
service.handleAbgabe(abgabeHandler);
}
}
@DisplayName("Evaluate abgabe")
@Nested
class TestEvaluateConfirmation {
@Mock
private XtaAbgabeHandler abgabeHandler;
private final ArchiveManagerCommand command = CommandTestFactory.create();
private final List<ArchiveManagerCommand> commands = List.of(command, command);
@Test
void shouldCallIsSuccessfullyDone() {
service.evaluateAbgabe(abgabeHandler, commands);
verify(abgabeHandler).isSuccessfullyDone();
}
@Test
void shouldCallPublishCommendExcecutedEvent() {
when(abgabeHandler.isSuccessfullyDone()).thenReturn(true);
service.evaluateAbgabe(abgabeHandler, commands);
verify(service, times(2)).publishCommandExecutedEvent(command);
}
@Test
void shouldCallPublishCommandFailedEvent() {
when(abgabeHandler.isSuccessfullyDone()).thenReturn(false);
service.evaluateAbgabe(abgabeHandler, commands);
verify(service, times(2)).publishCommandFailedEvent(abgabeHandler, command);
}
@DisplayName("on successfully done import confirmation")
@Nested
class TestPublishCommandExcutedEvent {
@Captor
private ArgumentCaptor<CommandExecutedEvent> commandExecutedEventCaptor;
@DisplayName("should publish command executed event")
@Test
void shouldPublishCommandExecutedEvent() {
service.publishCommandExecutedEvent(command);
verify(eventPublisher).publishEvent(commandExecutedEventCaptor.capture());
assertThat(commandExecutedEventCaptor.getValue().getCommand()).isEqualTo(command);
}
}
@DisplayName("on failed import confirmation")
@Nested
class TestPublishCommandFailedEvent {
@Captor
private ArgumentCaptor<CommandFailedEvent> commandFailedEventCaptor;
private final ArchiveManagerCommand command = CommandTestFactory.create();
@DisplayName("should publish command failed event")
@Test
void shouldPublishCommandFailedEvent() {
when(abgabeHandler.getFehlermeldung()).thenReturn(AbgabeImportBestaetigen0402TestFactory.FEHLERMELDUNG);
service.publishCommandFailedEvent(abgabeHandler, command);
verify(eventPublisher).publishEvent(commandFailedEventCaptor.capture());
assertThat(commandFailedEventCaptor.getValue().getSource()).isEqualTo(CommandTestFactory.ID);
assertThat(commandFailedEventCaptor.getValue().getErrorMessage()).isEqualTo(AbgabeImportBestaetigen0402TestFactory.FEHLERMELDUNG);
}
}
}
} }
package de.ozgcloud.archive.xta;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.springframework.context.ApplicationEventPublisher;
import de.ozgcloud.archive.common.command.ArchiveManagerCommand;
import de.ozgcloud.archive.common.command.CommandOrder;
import de.ozgcloud.archive.common.command.CommandService;
import de.ozgcloud.archive.common.command.CommandTestFactory;
import de.ozgcloud.archive.vorgang.VorgangWithEingangTestFactory;
import de.ozgcloud.archive.xta.XtaImportConfirmationHandler.XtaAbgabeHandler;
import de.ozgcloud.command.CommandExecutedEvent;
import de.ozgcloud.command.CommandFailedEvent;
import de.ozgcloud.common.errorhandling.TechnicalException;
import de.ozgcloud.xta.client.XtaClient;
import de.ozgcloud.xta.client.exception.XtaClientException;
import de.ozgcloud.xta.client.model.XtaMessage;
import lombok.SneakyThrows;
class XtaServiceTest {
@Spy
@InjectMocks
private XtaService service;
@Mock
private XtaClient client;
@Mock
private CommandService commandService;
@Mock
private ApplicationEventPublisher eventPublisher;
@Mock
private XtaFileHelper xtaFileHelper;
@DisplayName("Fetch messages")
@Nested
class TestFetchMessages {
@SneakyThrows
@Test
void shouldCallClient() {
service.fetchMessages();
verify(client).fetchMessages(any());
}
@SneakyThrows
@Test
void shouldThrowException() {
when(client.fetchMessages(any())).thenThrow(new XtaClientException("error-message"));
assertThatThrownBy(() -> service.fetchMessages()).isInstanceOf(TechnicalException.class);
}
}
@DisplayName("Consume message")
@Nested
class TestConsumeMessage {
@Mock
private XtaImportConfirmationHandler xtaFileContentHandler;
private final XtaMessage xtaMessage = XtaMessageTestFactory.create();
@Test
void shouldCallIsImportConfirmation() {
service.consumeMessage(xtaMessage);
verify(service).isImportConfirmation(XtaMessageTestFactory.MESSAGE_FILE);
}
@DisplayName("on import confirmation")
@Nested
class TestOnImportConfirmation {
@Mock
private XtaAbgabeHandler abgabeHandler;
@BeforeEach
void mock() {
doReturn(true).when(service).isImportConfirmation(any());
when(xtaFileHelper.initImportConfirmationHandler(any())).thenReturn(xtaFileContentHandler);
when(xtaFileContentHandler.getAbgaben()).thenReturn(Stream.of(abgabeHandler, abgabeHandler));
doNothing().when(service).handleAbgabe(any());
}
@Test
void shouldInitContentHandler() {
service.consumeMessage(xtaMessage);
verify(xtaFileHelper).initImportConfirmationHandler(XtaMessageTestFactory.MESSAGE_FILE);
}
@DisplayName("should handle import confirmation if type from document is matching")
@Test
void shouldCallHandleAbgabe() {
service.consumeMessage(xtaMessage);
verify(service, times(2)).handleAbgabe(abgabeHandler);
}
}
@DisplayName("should not handle message if its not an import confirmation")
@Test
void shouldNotProceed() {
doReturn(false).when(service).isImportConfirmation(any());
service.consumeMessage(xtaMessage);
verify(service, never()).handleAbgabe(any());
verify(xtaFileHelper, never()).initImportConfirmationHandler(any());
}
}
@DisplayName("Handle abgabe")
@Nested
class TestHandleAbgabe {
@Mock
private XtaAbgabeHandler abgabeHandler;
@BeforeEach
void mock() {
when(abgabeHandler.getVorgangId()).thenReturn(VorgangWithEingangTestFactory.ID);
when(commandService.findPending(any(), any())).thenReturn(Stream.empty());
}
@Test
void shouldGetVorgangId() {
handleImportConfirmation();
verify(abgabeHandler).getVorgangId();
}
@Test
void shouldCallCommandService() {
handleImportConfirmation();
verify(commandService).findPending(VorgangWithEingangTestFactory.ID, CommandOrder.ARCHIVE_VORGANG);
}
@DisplayName("on existing pending commands")
@Nested
class TestOnExistingPendingCommands {
private final ArchiveManagerCommand command = CommandTestFactory.create();
private final List<ArchiveManagerCommand> commands = List.of(command);
@BeforeEach
void mock() {
when(commandService.findPending(any(), any())).thenReturn(commands.stream());
doNothing().when(service).evaluateAbgabe(any(), any());
}
@Test
void shouldCallEvaluateConfirmation() {
handleImportConfirmation();
verify(service).evaluateAbgabe(abgabeHandler, commands);
}
}
@Test
void shouldNotCallEvaluateImportConfirmationOnEmptyList() {
handleImportConfirmation();
verify(service, never()).evaluateAbgabe(any(), any());
}
private void handleImportConfirmation() {
service.handleAbgabe(abgabeHandler);
}
}
@DisplayName("Evaluate abgabe")
@Nested
class TestEvaluateConfirmation {
@Mock
private XtaAbgabeHandler abgabeHandler;
private final ArchiveManagerCommand command = CommandTestFactory.create();
private final List<ArchiveManagerCommand> commands = List.of(command, command);
@Test
void shouldCallIsSuccessfullyDone() {
service.evaluateAbgabe(abgabeHandler, commands);
verify(abgabeHandler).isSuccessfullyDone();
}
@Test
void shouldCallPublishCommendExcecutedEvent() {
when(abgabeHandler.isSuccessfullyDone()).thenReturn(true);
service.evaluateAbgabe(abgabeHandler, commands);
verify(service, times(2)).publishCommandExecutedEvent(command);
}
@Test
void shouldCallPublishCommandFailedEvent() {
when(abgabeHandler.isSuccessfullyDone()).thenReturn(false);
service.evaluateAbgabe(abgabeHandler, commands);
verify(service, times(2)).publishCommandFailedEvent(abgabeHandler, command);
}
@DisplayName("on successfully done import confirmation")
@Nested
class TestPublishCommandExcutedEvent {
@Captor
private ArgumentCaptor<CommandExecutedEvent> commandExecutedEventCaptor;
@DisplayName("should publish command executed event")
@Test
void shouldPublishCommandExecutedEvent() {
service.publishCommandExecutedEvent(command);
verify(eventPublisher).publishEvent(commandExecutedEventCaptor.capture());
assertThat(commandExecutedEventCaptor.getValue().getCommand()).isEqualTo(command);
}
}
@DisplayName("on failed import confirmation")
@Nested
class TestPublishCommandFailedEvent {
@Captor
private ArgumentCaptor<CommandFailedEvent> commandFailedEventCaptor;
private final ArchiveManagerCommand command = CommandTestFactory.create();
@DisplayName("should publish command failed event")
@Test
void shouldPublishCommandFailedEvent() {
when(abgabeHandler.getFehlermeldung()).thenReturn(AbgabeImportBestaetigen0402TestFactory.FEHLERMELDUNG);
service.publishCommandFailedEvent(abgabeHandler, command);
verify(eventPublisher).publishEvent(commandFailedEventCaptor.capture());
assertThat(commandFailedEventCaptor.getValue().getSource()).isEqualTo(CommandTestFactory.ID);
assertThat(commandFailedEventCaptor.getValue().getErrorMessage()).isEqualTo(AbgabeImportBestaetigen0402TestFactory.FEHLERMELDUNG);
}
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment