Skip to content
Snippets Groups Projects
Commit e8b13c2a authored by Jan Zickermann's avatar Jan Zickermann
Browse files

Merge pull request...

Merge pull request 'OZG-6748-Duplizierte-Vorgaenge-Fuer-einen-Mantelantrag-part2' (#175) from OZG-6748-Duplizierte-Vorgaenge-Fuer-einen-Mantelantrag-part2 into master

Reviewed-on: https://git.ozg-sh.de/ozgcloud-app/eingang-manager/pulls/175


Reviewed-by: default avatarOZGCloud <ozgcloud@mgm-tp.com>
parents 946dbd6b 70473369
No related branches found
No related tags found
No related merge requests found
...@@ -18,7 +18,6 @@ import org.springframework.boot.context.properties.bind.Binder; ...@@ -18,7 +18,6 @@ import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.FormHeader; import de.ozgcloud.eingang.common.formdata.FormHeader;
import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle;
...@@ -67,78 +66,52 @@ public class MantelantragZustaendigeStelleMapper implements FormBasedMapper { ...@@ -67,78 +66,52 @@ public class MantelantragZustaendigeStelleMapper implements FormBasedMapper {
@Override @Override
public FormData parseFormData(FormData formData) { public FormData parseFormData(FormData formData) {
try { return formData.toBuilder()
return adaptFormDataWithPossibleException(formData); .clearZustaendigeStelles()
} catch (TechnicalException exception) { .zustaendigeStelles(getZustaendigeStelles(formData))
logWarningForFailure(exception); .build();
return formData;
}
} }
void logWarningForFailure(Exception exception) { List<ZustaendigeStelle> getZustaendigeStelles(FormData formData) {
LOG.warn("Failed mapping Zustaendigestelle of Mantelantrag: %s".formatted(exception.getMessage())); var fieldMap = formData.getFormData();
var matchingSlots = getMatchingSlots(fieldMap);
if (matchingSlots.isEmpty()) {
logErrorForNoMatchingIdentifiers();
}
return matchingSlots.stream()
.map(slotIndex -> getZustaendigeStelle(fieldMap, slotIndex))
.toList();
} }
FormData adaptFormDataWithPossibleException(FormData formData) { ZustaendigeStelle getZustaendigeStelle(Map<String, Object> fieldMap, int slotIndex) {
var fieldMap = formData.getFormData(); UnaryOperator<String> getValueOrEmpty = field -> getFieldByKeyOrEmpty(
var slotIndex = findSlotIndex(fieldMap);
return adaptFormDataWithValueGetter(formData, field -> getFieldByKeyOrEmpty(
fieldMap, fieldMap,
getNameForSlotIndex(field, slotIndex) getNameForSlotIndex(field, slotIndex)
)); );
var organisationseinheitId = getValueOrEmpty.apply(ORGANISATIONSEINHEIT_ID_FIELD);
if (organisationseinheitId.isBlank()) {
logWarningForEmptyOrganisationseinheitId(slotIndex);
} }
return ZustaendigeStelle.builder()
private FormData adaptFormDataWithValueGetter(FormData formData, UnaryOperator<String> getValueOrEmpty) { .organisationseinheitenId(organisationseinheitId)
return formData.toBuilder()
.zustaendigeStelle(ZustaendigeStelle.builder()
.organisationseinheitenId(getOrganisationseinheitId(getValueOrEmpty))
.bezeichnung(getValueOrEmpty.apply(BEZEICHNUNG_FIELD)) .bezeichnung(getValueOrEmpty.apply(BEZEICHNUNG_FIELD))
.email(getValueOrEmpty.apply(EMAIL_FIELD)) .email(getValueOrEmpty.apply(EMAIL_FIELD))
.hausanschriftStrasse(getValueOrEmpty.apply(HAUSANSCHRIFT_STRASSE_FIELD)) .hausanschriftStrasse(getValueOrEmpty.apply(HAUSANSCHRIFT_STRASSE_FIELD))
.hausanschriftPlz(getValueOrEmpty.apply(HAUSANSCHRIFT_PLZ_FIELD)) .hausanschriftPlz(getValueOrEmpty.apply(HAUSANSCHRIFT_PLZ_FIELD))
.hausanschriftOrt(getValueOrEmpty.apply(HAUSANSCHRIFT_ORT_FIELD)) .hausanschriftOrt(getValueOrEmpty.apply(HAUSANSCHRIFT_ORT_FIELD))
.telefon(getValueOrEmpty.apply(TELEFON_FIELD)) .telefon(getValueOrEmpty.apply(TELEFON_FIELD))
.build())
.build(); .build();
} }
private String getOrganisationseinheitId(UnaryOperator<String> getValueOrEmpty) { void logWarningForEmptyOrganisationseinheitId(int slotIndex) {
var organisationseinheitId = getValueOrEmpty.apply(ORGANISATIONSEINHEIT_ID_FIELD); LOG.warn("[Mantelantrag] OrganisationseinheitId for slot {} is empty!", slotIndex);
if (organisationseinheitId.isBlank()) {
throw new TechnicalException("OrganistaionseinheitId not found!");
}
return organisationseinheitId;
}
int findSlotIndex(Map<String, Object> fieldMap) {
var matchingSlots = getMatchingSlots(fieldMap);
verifyOneMatchingIdentifier(matchingSlots);
return matchingSlots.getFirst();
}
private void verifyOneMatchingIdentifier(List<Integer> matchingSlots) {
if (matchingSlots.size() != 1) {
var message = getMultipleSlotsMessage(matchingSlots);
if (matchingSlots.isEmpty()) {
throw new TechnicalException(message);
} else {
logWarningForUnexpected(message);
}
}
}
void logWarningForUnexpected(String message) {
LOG.warn("Unexpected Zustaendigestelle in Mantelantrag: %s".formatted(message));
} }
String getMultipleSlotsMessage(List<Integer> matchingSlots) { void logErrorForNoMatchingIdentifiers() {
return "Found %d matching nachrichtenbroker addresses! Expected one of '%s'.".formatted(matchingSlots.size(), LOG.error("[Mantelantrag] No matching Zustaendigestelle found! For identifiers: '{}'.", Strings.join(xtaIdentifiers, ','));
Strings.join(xtaIdentifiers, ','));
} }
private List<Integer> getMatchingSlots(Map<String, Object> fieldMap) { List<Integer> getMatchingSlots(Map<String, Object> fieldMap) {
return IntStream.range(0, 3) return IntStream.range(0, 3)
.filter(slotIndex -> xtaIdentifiers.contains(getXtaIdentifierOfSlot(fieldMap, slotIndex))) .filter(slotIndex -> xtaIdentifiers.contains(getXtaIdentifierOfSlot(fieldMap, slotIndex)))
.boxed() .boxed()
......
package de.ozgcloud.eingang.semantik.formbased.mantelantrag; package de.ozgcloud.eingang.semantik.formbased.mantelantrag;
import static de.ozgcloud.eingang.common.formdata.FormDataTestFactory.*;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*; import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
...@@ -7,76 +8,154 @@ import static org.mockito.Mockito.*; ...@@ -7,76 +8,154 @@ import static org.mockito.Mockito.*;
import java.io.File; import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName; 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.ArgumentCaptor;
import org.mockito.Captor; import org.mockito.Captor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import de.ozgcloud.common.binaryfile.TempFileUtils; import de.ozgcloud.common.binaryfile.TempFileUtils;
import de.ozgcloud.common.test.TestUtils; import de.ozgcloud.common.test.TestUtils;
import de.ozgcloud.eingang.Application; import de.ozgcloud.eingang.Application;
import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory; import de.ozgcloud.eingang.common.formdata.IncomingFileTestFactory;
import de.ozgcloud.eingang.common.formdata.ZustaendigeStelle; import de.ozgcloud.eingang.router.VorgangRemoteService;
import de.ozgcloud.eingang.router.VorgangService;
import de.ozgcloud.eingang.semantik.SemantikAdapter; import de.ozgcloud.eingang.semantik.SemantikAdapter;
import de.ozgcloud.eingang.semantik.enginebased.formsolutions.FormSolutionsEngineBasedAdapterITCase; import de.ozgcloud.eingang.semantik.enginebased.formsolutions.FormSolutionsEngineBasedAdapterITCase;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@ActiveProfiles({ "local", "itcase" }) @ActiveProfiles({ "local", "itcase" })
@SpringBootTest(classes = Application.class, properties = { "ozgcloud.xta.identifiers=afmsh:ozg-cloud-utopia-test" }) @SpringBootTest(classes = Application.class)
public class MantelantragITCase { public class MantelantragITCase {
private static final String FILE_NAME_XDOMEA = "mantelantrag/4620-EH6C_b3c9168a-6ae9-4361-8b2f-6837bb341021_Geschaeftsgang.Geschaeftsgang.0201.xml"; private static final String FILE_NAME_XDOMEA = "mantelantrag/4620-EH6C_b3c9168a-6ae9-4361-8b2f-6837bb341021_Geschaeftsgang.Geschaeftsgang.0201.xml";
private static final String FILE_NAME_MANTELANTRAG = "mantelantrag/4620-EH6C_7d703670-15b6-42b2-8cd1-88a7e4c494b9_Antrag_Max_Mustermann_SGBXII.xml"; private static final String FILE_NAME_MANTELANTRAG = "mantelantrag/4620-EH6C_7d703670-15b6-42b2-8cd1-88a7e4c494b9_Antrag_Max_Mustermann_SGBXII.xml";
@MockBean @MockBean
VorgangService vorgangService; VorgangRemoteService vorgangRemoteService;
@SpyBean @SpyBean
SemantikAdapter semantikAdapter; SemantikAdapter semantikAdapter;
@Nested
class TestZustaendigeStelle {
@Captor @Captor
ArgumentCaptor<FormData> formDataCaptor; ArgumentCaptor<FormData> formDataCaptor;
private FormData formData;
private static final String VORGANG_ID_1 = "vorgangId1"; @Captor
ArgumentCaptor<Optional<String>> oeIdCaptor;
@Autowired
MantelantragZustaendigeStelleMapper mantelantragZustaendigeStelleMapper;
static List<String> xtaIdentifiers = Collections.emptyList();
@BeforeEach @BeforeEach
void mock() { void mock() {
doReturn(VORGANG_ID_1).when(vorgangService).createVorgang(any()); clearInvocations(vorgangRemoteService);
doReturn(VORGANG_ID).when(vorgangRemoteService).createVorgang(any(FormData.class), any());
formData = prepareTestData();
mantelantragZustaendigeStelleMapper.init();
} }
@DisplayName("should return first vorgangId") @DynamicPropertySource
static void dynamicProperties(DynamicPropertyRegistry registry) {
registry.add("ozgcloud.xta.identifiers", () -> xtaIdentifiers);
}
@DisplayName("without matching zustaendige stelle")
@Nested
class TestWithoutMatchingZustaendigeStelle {
@BeforeAll
static void setup() {
xtaIdentifiers = List.of("afmsh:unknown");
}
@DisplayName("should create one vorgang")
@Test @Test
void shouldReturnFirstVorgangId() { void shouldCreateOneVorgang() {
var result = semantikAdapter.processFormData(prepareTestData()); semantikAdapter.processFormData(formData);
verify(vorgangRemoteService, times(1)).createVorgang(formDataCaptor.capture(), oeIdCaptor.capture());
assertThat(oeIdCaptor.getValue()).isEmpty();
}
}
assertThat(result).isEqualTo(VORGANG_ID_1); @DisplayName("with one matching zustaendige stelle")
@Nested
class TestWithOneMatchingZustaendigeStelle {
@BeforeAll
static void setup() {
xtaIdentifiers = List.of("afmsh:ozg-cloud-utopia-test");
} }
@DisplayName("should pass organisationseinheit id to create vorgang") @DisplayName("should create one vorgang")
@Test @Test
void shouldPassOrganisationseinheitIdToCreateVorgang() { void shouldCreateOneVorgang() {
semantikAdapter.processFormData(prepareTestData()); semantikAdapter.processFormData(formData);
verify(vorgangService).createVorgang(formDataCaptor.capture()); verify(vorgangRemoteService, times(1)).createVorgang(formDataCaptor.capture(), oeIdCaptor.capture());
assertThat(formDataCaptor.getValue().getZustaendigeStelles()) assertThat(oeIdCaptor.getValue()).contains("123");
.extracting(ZustaendigeStelle::getOrganisationseinheitenId) }
.containsExactly("123");
} }
@DisplayName("with two matching zustaendige stelle")
@Nested
class TestWithTwoMatchingZustaendigeStelle {
@BeforeAll
static void setup() {
xtaIdentifiers = List.of("afmsh:ozg-cloud-utopia-test", "gae:ozg-cloud-itcase-test");
}
@DisplayName("should create two vorangs with partially matching zustaendigeStelle")
@Test
void shouldCreateTwoVorangsWithPartiallyMatchingZustaendigeStelle() {
semantikAdapter.processFormData(formData);
verify(vorgangRemoteService, times(2)).createVorgang(formDataCaptor.capture(), oeIdCaptor.capture());
assertThat(oeIdCaptor.getAllValues()).contains(Optional.of("123"), Optional.of("444"));
}
}
@DisplayName("with three matching zustaendige stelles")
@Nested
class TestWithThreeMatchingZustaendigeStelles {
@BeforeAll
static void setup() {
xtaIdentifiers = List.of("afmsh:ozg-cloud-utopia-test", "gae:ozg-cloud-itcase-test", "afmsh:ozg-cloud-bad-segeberg-kreis");
}
@DisplayName("should create three vorgangs")
@Test
void shouldCreateThreeVorgangs() {
semantikAdapter.processFormData(formData);
verify(vorgangRemoteService, times(3)).createVorgang(formDataCaptor.capture(), oeIdCaptor.capture());
assertThat(oeIdCaptor.getAllValues()).contains(Optional.of("123"), Optional.of("321"), Optional.of("444"));
}
}
@DisplayName("should return first vorgangId")
@Test
void shouldReturnFirstVorgangId() {
var result = semantikAdapter.processFormData(formData);
assertThat(result).isEqualTo(VORGANG_ID);
} }
private FormData prepareTestData() { private FormData prepareTestData() {
......
package de.ozgcloud.eingang.semantik.formbased.mantelantrag; package de.ozgcloud.eingang.semantik.formbased.mantelantrag;
import static de.ozgcloud.eingang.semantik.formbased.mantelantrag.MantelantragZustaendigeStelleMapper.*; import static de.ozgcloud.eingang.semantik.formbased.mantelantrag.MantelantragZustaendigeStelleMapper.*;
import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
...@@ -18,13 +19,10 @@ import org.junit.jupiter.params.ParameterizedTest; ...@@ -18,13 +19,10 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource; import org.junit.jupiter.params.provider.ValueSource;
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.Spy; import org.mockito.Spy;
import de.ozgcloud.eingang.common.errorhandling.TechnicalException;
import de.ozgcloud.eingang.common.formdata.FormData; import de.ozgcloud.eingang.common.formdata.FormData;
import de.ozgcloud.eingang.common.formdata.FormDataTestFactory; import de.ozgcloud.eingang.common.formdata.FormDataTestFactory;
import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory; import de.ozgcloud.eingang.common.formdata.FormHeaderTestFactory;
...@@ -107,53 +105,104 @@ class MantelantragZustaendigeStelleMapperTest { ...@@ -107,53 +105,104 @@ class MantelantragZustaendigeStelleMapperTest {
} }
} }
@DisplayName("adapt form data") @DisplayName("parse form data")
@Nested @Nested
class TestAdaptFormData { class TestParseFormData {
private FormData formData;
@Mock @Mock
private ZustaendigeStelle zustaendigeStelle;
@BeforeEach
void mock() {
formData = FormDataTestFactory.create();
}
@DisplayName("should override zustaendige stelles")
@Test
void shouldOverrideZustaendigeStelles() {
doReturn(List.of(zustaendigeStelle)).when(mapper).getZustaendigeStelles(formData);
var result = mapper.parseFormData(formData);
assertThat(result.getZustaendigeStelles()).containsExactly(zustaendigeStelle);
}
@DisplayName("should keep other formdata fields")
@Test
void shouldKeepOtherFormdataFields() {
doReturn(formData.getZustaendigeStelles()).when(mapper).getZustaendigeStelles(formData);
var result = mapper.parseFormData(formData);
assertThat(result).usingRecursiveComparison().isEqualTo(formData);
}
}
@DisplayName("get zustaendige stelles")
@Nested
class TestGetZustaendigeStelles {
private FormData formData; private FormData formData;
@Mock @Mock
private FormData formData2; private Map<String, Object> fieldMap;
@Mock
private ZustaendigeStelle stelle1;
@Mock
private ZustaendigeStelle stelle2;
@Mock
private ZustaendigeStelle stelle3;
@DisplayName("should return adapted value") @BeforeEach
void mock() {
formData = FormDataTestFactory.createBuilder()
.formData(fieldMap)
.build();
}
@DisplayName("should return")
@Test @Test
void shouldReturnAdaptedValue() { void shouldReturn() {
doReturn(formData2).when(mapper).adaptFormDataWithPossibleException(formData); doReturn(emptyList()).when(mapper).getMatchingSlots(fieldMap);
var resultFormData = mapper.parseFormData(formData); var result = mapper.getZustaendigeStelles(formData);
assertThat(resultFormData).isEqualTo(formData2); assertThat(result).isEmpty();
} }
@DisplayName("should return original value with exception") @DisplayName("should log error for no matching identifiers")
@Test @Test
void shouldReturnOriginalValueWithException() { void shouldLogErrorForNoMatchingIdentifiers() {
doThrow(new TechnicalException("some error")).when(mapper).adaptFormDataWithPossibleException(formData); doReturn(emptyList()).when(mapper).getMatchingSlots(fieldMap);
var resultFormData = mapper.parseFormData(formData); mapper.getZustaendigeStelles(formData);
assertThat(resultFormData).isEqualTo(formData); verify(mapper).logErrorForNoMatchingIdentifiers();
} }
@DisplayName("should log warning with exception") @DisplayName("should return with three zustaendige stelle")
@Test @Test
void shouldLogWarningWithException() { void shouldReturnWithThreeZustaendigeStelle() {
var exception = new TechnicalException("some error"); doReturn(List.of(0, 1, 2)).when(mapper).getMatchingSlots(fieldMap);
doThrow(exception).when(mapper).adaptFormDataWithPossibleException(formData); doReturn(stelle1).when(mapper).getZustaendigeStelle(fieldMap, 0);
doReturn(stelle2).when(mapper).getZustaendigeStelle(fieldMap, 1);
doReturn(stelle3).when(mapper).getZustaendigeStelle(fieldMap, 2);
mapper.parseFormData(formData); var result = mapper.getZustaendigeStelles(formData);
verify(mapper).logWarningForFailure(exception); assertThat(result).containsExactly(stelle1, stelle2, stelle3);
} }
} }
@DisplayName("adapt form data with possible exception") @DisplayName("get zustaendige stelle")
@Nested @Nested
class TestAdaptFormDataWithPossibleException { class TestGetZustaendigeStelle {
static final String TARGET_OPTIONAL_FIELD_VALUE = "optionalFieldValue";
static final Map<String, Function<ZustaendigeStelle, String>> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR = Map.of( static final Map<String, Function<ZustaendigeStelle, String>> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR = Map.of(
BEZEICHNUNG_FIELD, ZustaendigeStelle::getBezeichnung, BEZEICHNUNG_FIELD, ZustaendigeStelle::getBezeichnung,
EMAIL_FIELD, ZustaendigeStelle::getEmail, EMAIL_FIELD, ZustaendigeStelle::getEmail,
...@@ -162,17 +211,8 @@ class MantelantragZustaendigeStelleMapperTest { ...@@ -162,17 +211,8 @@ class MantelantragZustaendigeStelleMapperTest {
HAUSANSCHRIFT_ORT_FIELD, ZustaendigeStelle::getHausanschriftOrt, HAUSANSCHRIFT_ORT_FIELD, ZustaendigeStelle::getHausanschriftOrt,
TELEFON_FIELD, ZustaendigeStelle::getTelefon TELEFON_FIELD, ZustaendigeStelle::getTelefon
); );
private FormData formData;
private Map<String, Object> fieldMap; private Map<String, Object> fieldMap;
private static Stream<Arguments> fieldNameAndSlotIndex() {
return Stream.of(0, 1, 2)
.flatMap(slotIndex -> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR
.keySet().stream()
.map(fieldName -> Arguments.of(slotIndex, fieldName))
);
}
@BeforeEach @BeforeEach
void mock() { void mock() {
fieldMap = new HashMap<>(Map.of( fieldMap = new HashMap<>(Map.of(
...@@ -180,22 +220,6 @@ class MantelantragZustaendigeStelleMapperTest { ...@@ -180,22 +220,6 @@ class MantelantragZustaendigeStelleMapperTest {
getOrganisationseinheitIDFieldName(2), "", getOrganisationseinheitIDFieldName(2), "",
getOrganisationseinheitIDFieldName(10), "1111111" getOrganisationseinheitIDFieldName(10), "1111111"
)); ));
formData = FormDataTestFactory.createBuilder()
.clearZustaendigeStelles()
.formData(fieldMap)
.build();
}
@DisplayName("should keep form data except zustaendigestelle")
@Test
void shouldKeepFormDataExceptZustaendigestelle() {
doReturn(10).when(mapper).findSlotIndex(fieldMap);
var resultFormData = mapper.parseFormData(formData);
assertThat(resultFormData.getId()).isEqualTo(formData.getId());
assertThat(resultFormData.getHeader()).isEqualTo(formData.getHeader());
assertThat(resultFormData.getAntragsteller()).isEqualTo(formData.getAntragsteller());
} }
@DisplayName("should map organisationseinheitId") @DisplayName("should map organisationseinheitId")
...@@ -204,7 +228,7 @@ class MantelantragZustaendigeStelleMapperTest { ...@@ -204,7 +228,7 @@ class MantelantragZustaendigeStelleMapperTest {
void shouldMapOrganisationseinheitId(int slotIndex) { void shouldMapOrganisationseinheitId(int slotIndex) {
mockWithOEID(slotIndex, TARGET_OEID); mockWithOEID(slotIndex, TARGET_OEID);
var zustaendigeStelle = getAdaptedZustaendigeStelle(); var zustaendigeStelle = getZustaendigeStelle(slotIndex);
assertThat(zustaendigeStelle.getOrganisationseinheitenId()).isEqualTo(TARGET_OEID); assertThat(zustaendigeStelle.getOrganisationseinheitenId()).isEqualTo(TARGET_OEID);
} }
...@@ -213,62 +237,60 @@ class MantelantragZustaendigeStelleMapperTest { ...@@ -213,62 +237,60 @@ class MantelantragZustaendigeStelleMapperTest {
return mapper.getNameForSlotIndex(ORGANISATIONSEINHEIT_ID_FIELD, slotIndex); return mapper.getNameForSlotIndex(ORGANISATIONSEINHEIT_ID_FIELD, slotIndex);
} }
@DisplayName("should throw if organistaionseinheitId is missing") @DisplayName("should log warning if organistaionseinheitId is missing")
@ParameterizedTest @ParameterizedTest
@ValueSource(ints = { 0, 1, 2 }) @ValueSource(ints = { 0, 1, 2 })
void shouldThrowIfOrganistationseinheitIdIsMissing(int slotIndex) { void shouldLogWarningIfOrganistaionseinheitIdIsMissing(int slotIndex) {
doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap); getZustaendigeStelle(slotIndex);
assertThatThrownBy(this::getAdaptedZustaendigeStelle) verify(mapper).logWarningForEmptyOrganisationseinheitId(slotIndex);
.isInstanceOf(TechnicalException.class);
}
@DisplayName("should throw if organistationseinheitId is empty")
@ParameterizedTest
@ValueSource(ints = { 0, 1, 2 })
void shouldThrowIfOrganistationseinheitIdIsEmpty(int slotIndex) {
mockWithOEID(slotIndex, "");
assertThatThrownBy(this::getAdaptedZustaendigeStelle)
.isInstanceOf(TechnicalException.class);
} }
@DisplayName("should map optional field") @DisplayName("should map optional field")
@ParameterizedTest @ParameterizedTest
@MethodSource("fieldNameAndSlotIndex") @MethodSource("generateFieldNameAndSlotIndex")
void shouldMapOptionalField(int slotIndex, String fieldName) { void shouldMapOptionalField(int slotIndex, String fieldName) {
mockWithSomeOEID(slotIndex); mockWithSomeOEID(slotIndex);
fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), TARGET_OPTIONAL_FIELD_VALUE); var optionalFieldValue = "value of '%s'".formatted(fieldName);
fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), optionalFieldValue);
var zustaendigeStelle = getAdaptedZustaendigeStelle(); var zustaendigeStelle = getZustaendigeStelle(slotIndex);
assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEqualTo(TARGET_OPTIONAL_FIELD_VALUE); assertThat(getExpectedValueByFieldName(zustaendigeStelle, fieldName)).isEqualTo(optionalFieldValue);
} }
@DisplayName("should map missing optional fields to empty") @DisplayName("should map missing optional fields to empty")
@ParameterizedTest @ParameterizedTest
@MethodSource("fieldNameAndSlotIndex") @MethodSource("generateFieldNameAndSlotIndex")
void shouldMapMissingOptionalFieldsToEmpty(int slotIndex, String fieldName) { void shouldMapMissingOptionalFieldsToEmpty(int slotIndex, String fieldName) {
mockWithSomeOEID(slotIndex); mockWithSomeOEID(slotIndex);
var zustaendigeStelle = getAdaptedZustaendigeStelle(); var zustaendigeStelle = getZustaendigeStelle(slotIndex);
assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEmpty(); assertThat(getExpectedValueByFieldName(zustaendigeStelle, fieldName)).isEmpty();
} }
@DisplayName("should map empty optional fields to empty") @DisplayName("should map empty optional fields to empty")
@ParameterizedTest @ParameterizedTest
@MethodSource("fieldNameAndSlotIndex") @MethodSource("generateFieldNameAndSlotIndex")
void shouldMapEmptyOptionalFieldsToEmpty(int slotIndex, String fieldName) { void shouldMapEmptyOptionalFieldsToEmpty(int slotIndex, String fieldName) {
mockWithSomeOEID(slotIndex); mockWithSomeOEID(slotIndex);
fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), ""); fieldMap.put(mapper.getNameForSlotIndex(fieldName, slotIndex), "");
var zustaendigeStelle = getAdaptedZustaendigeStelle(); var zustaendigeStelle = getZustaendigeStelle(slotIndex);
assertThat(getExpectedByFieldName(zustaendigeStelle, fieldName)).isEmpty(); assertThat(getExpectedValueByFieldName(zustaendigeStelle, fieldName)).isEmpty();
} }
private String getExpectedByFieldName(ZustaendigeStelle zustaendigeStelle, String fieldName) { private static Stream<Arguments> generateFieldNameAndSlotIndex() {
return Stream.of(0, 1, 2)
.flatMap(slotIndex -> FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR
.keySet().stream()
.map(fieldName -> Arguments.of(slotIndex, fieldName))
);
}
private String getExpectedValueByFieldName(ZustaendigeStelle zustaendigeStelle, String fieldName) {
var valueExtractor = FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR.get(fieldName); var valueExtractor = FIELD_NAME_TO_EXPECTED_VALUE_EXTRACTOR.get(fieldName);
return valueExtractor.apply(zustaendigeStelle); return valueExtractor.apply(zustaendigeStelle);
} }
...@@ -279,25 +301,20 @@ class MantelantragZustaendigeStelleMapperTest { ...@@ -279,25 +301,20 @@ class MantelantragZustaendigeStelleMapperTest {
private void mockWithOEID(int slotIndex, String targetOeid) { private void mockWithOEID(int slotIndex, String targetOeid) {
fieldMap.put(getOrganisationseinheitIDFieldName(slotIndex), targetOeid); fieldMap.put(getOrganisationseinheitIDFieldName(slotIndex), targetOeid);
doReturn(slotIndex).when(mapper).findSlotIndex(fieldMap);
} }
private ZustaendigeStelle getAdaptedZustaendigeStelle() { private ZustaendigeStelle getZustaendigeStelle(int slotIndex) {
var formDataResult = mapper.adaptFormDataWithPossibleException(formData); return mapper.getZustaendigeStelle(fieldMap, slotIndex);
return formDataResult.getZustaendigeStelles().getFirst();
} }
} }
@DisplayName("find slot index") @DisplayName("get matching slots")
@Nested @Nested
class TestFindSlotIndex { class TestGetMatchingSlots {
private Map<String, Object> fieldMap; private Map<String, Object> fieldMap;
@Captor
private ArgumentCaptor<String> warningCaptor;
@BeforeEach @BeforeEach
void mock() { void mock() {
fieldMap = new HashMap<>(Map.of( fieldMap = new HashMap<>(Map.of(
...@@ -306,15 +323,23 @@ class MantelantragZustaendigeStelleMapperTest { ...@@ -306,15 +323,23 @@ class MantelantragZustaendigeStelleMapperTest {
)); ));
} }
@DisplayName("should return matching slot") @DisplayName("should return empty")
@Test
void shouldReturnEmpty() {
var resultSlotIndices = mapper.getMatchingSlots(fieldMap);
assertThat(resultSlotIndices).isEmpty();
}
@DisplayName("should return matching slots")
@ParameterizedTest @ParameterizedTest
@ValueSource(ints = { 0, 1, 2 }) @ValueSource(ints = { 0, 1, 2 })
void shouldReturnMatchingSlot(int slotIndex) { void shouldReturnMatchingSlot(int slotIndex) {
fieldMap.put(getZustaendigeStelleName(slotIndex), IDENTIFIER); fieldMap.put(getZustaendigeStelleName(slotIndex), IDENTIFIER);
var resultSlotIndex = mapper.findSlotIndex(fieldMap); var resultSlotIndices = mapper.getMatchingSlots(fieldMap);
assertThat(resultSlotIndex).isEqualTo(slotIndex); assertThat(resultSlotIndices).containsExactly(slotIndex);
} }
@DisplayName("should return matching slot with upper-/lowercase difference in identifiers") @DisplayName("should return matching slot with upper-/lowercase difference in identifiers")
...@@ -323,33 +348,14 @@ class MantelantragZustaendigeStelleMapperTest { ...@@ -323,33 +348,14 @@ class MantelantragZustaendigeStelleMapperTest {
void shouldReturnMatchingSlotWithUppercaseIdentifier(int slotIndex) { void shouldReturnMatchingSlotWithUppercaseIdentifier(int slotIndex) {
fieldMap.put(getZustaendigeStelleName(slotIndex), IDENTIFIER2UPPERCASE); fieldMap.put(getZustaendigeStelleName(slotIndex), IDENTIFIER2UPPERCASE);
var resultSlotIndex = mapper.findSlotIndex(fieldMap); var resultSlotIndex = mapper.getMatchingSlots(fieldMap);
assertThat(resultSlotIndex).isEqualTo(slotIndex); assertThat(resultSlotIndex).containsExactly(slotIndex);
} }
private String getZustaendigeStelleName(int slotIndex) { private String getZustaendigeStelleName(int slotIndex) {
return mapper.getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex); return mapper.getNameForSlotIndex(ZUSTELLUNG_NACHRICHTENBROKER_FIELD, slotIndex);
} }
@DisplayName("should throw if no slot matches")
@Test
void shouldThrowIfNoSlotMatches() {
assertThatThrownBy(() -> mapper.findSlotIndex(fieldMap))
.isInstanceOf(TechnicalException.class);
}
@DisplayName("should log warning if multiple slots match")
@Test
void shouldLogWarningIfMultipleSlotsMatch() {
fieldMap.put(getZustaendigeStelleName(0), IDENTIFIER2);
fieldMap.put(getZustaendigeStelleName(2), IDENTIFIER);
mapper.findSlotIndex(fieldMap);
verify(mapper).logWarningForUnexpected(warningCaptor.capture());
assertThat(warningCaptor.getValue()).isEqualTo(mapper.getMultipleSlotsMessage(List.of(0, 2)));
}
} }
@DisplayName("get name for slot index") @DisplayName("get name for slot index")
......
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
<zustellung_nachrichtenbroker2>afmsh:ozg-cloud-bad-segeberg-kreis</zustellung_nachrichtenbroker2> <zustellung_nachrichtenbroker2>afmsh:ozg-cloud-bad-segeberg-kreis</zustellung_nachrichtenbroker2>
<zustellung_email_ln2/> <zustellung_email_ln2/>
<zustellung_webservice2/> <zustellung_webservice2/>
<kontaktsystem_oeid3/> <kontaktsystem_oeid3>444</kontaktsystem_oeid3>
<OrganisationseinheitenBEZEICHNUNG3/> <OrganisationseinheitenBEZEICHNUNG3/>
<zust_strasse3/> <zust_strasse3/>
<zust_hausnummer3/> <zust_hausnummer3/>
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
<zust_telefonnummer3/> <zust_telefonnummer3/>
<zust_faxnummer3/> <zust_faxnummer3/>
<zust_emailadresse3/> <zust_emailadresse3/>
<zustellung_nachrichtenbroker3/> <zustellung_nachrichtenbroker3>gae:ozg-cloud-itcase-test</zustellung_nachrichtenbroker3>>
<zustellung_email_ln3/> <zustellung_email_ln3/>
<zustellung_webservice3/> <zustellung_webservice3/>
<grund>Hilfe</grund> <grund>Hilfe</grund>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment