diff options
author | Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at> | 2019-07-22 13:02:19 +0200 |
---|---|---|
committer | Christof Rabensteiner <christof.rabensteiner@iaik.tugraz.at> | 2019-07-22 13:02:19 +0200 |
commit | cb9a76eaafd37f921006822bcfe043655288bc63 (patch) | |
tree | 76c2463e181ac293134f4c5bfc7e342607f3f399 /src/test/java/at | |
parent | d873625c0ced62e712dc1b1a7570b63482fd0a0a (diff) | |
download | moa-zs-cb9a76eaafd37f921006822bcfe043655288bc63.tar.gz moa-zs-cb9a76eaafd37f921006822bcfe043655288bc63.tar.bz2 moa-zs-cb9a76eaafd37f921006822bcfe043655288bc63.zip |
Test Flow of DeliveryRequest from "End-To-End" & Fix Bugs
Schema Changes:
- Remove mzs:DeliveryRequest/TnvzMetaData because all metadata fields
can be collected from DeliveryRequest and redundancy is not needed.
Fixes and Refactoring in preprocess:
- MzsDeliveryRequestValidator: Instead of returning false, throw an
exception when a condition is not met, and explain which condition
is not met / why it is not met in the exception's message.
- Integrate interface change in ConfigProfileGenerator and
DeliveryRequestAugmenter.
- Rewrite and simplify DeliveryRequestAugmenter's augmentation.
- ConfigUtil Fixes: Ensure that we do not override the wrong
parameters while merging. This error appeared in tnvz / msg client,
connection / receive timeout, key / trust store, and lax hostname
verification / trust all.
Fix Bugs in Interceptor / SoapUtils:
- Problem: DOM access and information extraction was implemented
somewhat sloppy.
- SolutioN: Change DOM access interface to access DOM more
efficiently. Add boundary checks and handle edge cases while
extracting information from SOAP Messages.
- Test those changes properly.
Testing:
- Implement Delivery Request Flow in ITEndToEndTest.
- Start application on random port instead of fixed port when running
integration tests.
- Add assertions to tests in ITMzsServiceTest suite.
Others Bug Fixes:
- ServicesConfig: Ensure that mzs service and msg service run on
different endpoint addresses (/msg and /mzs).
- DeliveryRequestBackend: Throw exception when binary message is
missing. Don't wrap the exception.
- SaveResponseToFileSink: Wrap Response in JAXB Element (otherwise,
marshaller does not recognize it)
Diffstat (limited to 'src/test/java/at')
6 files changed, 436 insertions, 44 deletions
diff --git a/src/test/java/at/gv/egiz/moazs/ConfigProfileGeneratorTest.java b/src/test/java/at/gv/egiz/moazs/ConfigProfileGeneratorTest.java index f408c3b..c056b2c 100644 --- a/src/test/java/at/gv/egiz/moazs/ConfigProfileGeneratorTest.java +++ b/src/test/java/at/gv/egiz/moazs/ConfigProfileGeneratorTest.java @@ -5,10 +5,12 @@ import at.gv.egiz.moazs.preprocess.*; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import java.util.Map; +import static at.gv.egiz.moazs.MoaZSException.moaZSException; import static at.gv.egiz.moazs.preprocess.ConfigProfileGenerator.configProfileGeneratorBuilder; import static at.gv.zustellung.app2mzs.xsd.ConfigType.configTypeBuilder; import static org.mockito.ArgumentMatchers.any; @@ -91,7 +93,7 @@ public class ConfigProfileGeneratorTest { public void cancelAtIncompleteDefaultProfile() { var propMap = Map.of(PREFIX + "." + DEFAULT + ".property-a", "value-a"); var generator = setupMocksAndBuilder(propMap).build(); - when(validator.isConfigProfileComplete(any())).thenReturn(false); + doThrow(moaZSException("Not Complete.")).when(validator).isConfigProfileComplete(any()); generator.generate(); } @@ -100,7 +102,7 @@ public class ConfigProfileGeneratorTest { public void continueAtIncompleteDefaultWhenVerificationDisabled() { var propMap = Map.of(PREFIX + "." + DEFAULT + ".property-a", "value-a"); - when(validator.isConfigProfileComplete(any())).thenReturn(false); + doThrow(moaZSException("Not Complete.")).when(validator).isConfigProfileComplete(any()); var generator = setupMocksAndBuilder(propMap) .withVerifyCompletenessOfDefaultConfiguration(false) @@ -117,7 +119,6 @@ public class ConfigProfileGeneratorTest { when(properties.getProperty(any())).thenAnswer(i -> propMap.get(i.getArgument(0))); when(util.merge(any(), any())).thenAnswer(i -> i.getArgument(0)); when(util.convert(any())).thenReturn(configTypeBuilder().build()); - when(validator.isConfigProfileComplete(any())).thenReturn(true); return configProfileGeneratorBuilder() .withProperties(properties) diff --git a/src/test/java/at/gv/egiz/moazs/DeliveryRequestAugmenterTest.java b/src/test/java/at/gv/egiz/moazs/DeliveryRequestAugmenterTest.java index 12f1dea..2e9dd80 100644 --- a/src/test/java/at/gv/egiz/moazs/DeliveryRequestAugmenterTest.java +++ b/src/test/java/at/gv/egiz/moazs/DeliveryRequestAugmenterTest.java @@ -3,6 +3,7 @@ package at.gv.egiz.moazs; import at.gv.egiz.moazs.preprocess.MzsDeliveryRequestValidator; import at.gv.egiz.moazs.preprocess.ConfigUtil; import at.gv.egiz.moazs.preprocess.DeliveryRequestAugmenter; +import at.gv.egiz.moazs.scheme.Marshaller; import at.gv.zustellung.app2mzs.xsd.ConfigType; import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType; import org.junit.Before; @@ -31,10 +32,10 @@ public class DeliveryRequestAugmenterTest { @Mock private MzsDeliveryRequestValidator validator; + private Marshaller mzsMarshaller = new Marshaller(true); + @Before public void setupMock() { - when(validator.isConfigProfileComplete(any())).thenReturn(true); - when(validator.isTnvzComplete(any())).thenReturn(true); when(configUtil.merge(any(), any())).thenCallRealMethod(); } @@ -109,11 +110,11 @@ public class DeliveryRequestAugmenterTest { } private DeliveryRequestAugmenter createAugmenter(ConfigType fallback) { - return new DeliveryRequestAugmenter(Map.of("default", fallback), configUtil, validator); + return new DeliveryRequestAugmenter(Map.of("default", fallback), configUtil, validator, mzsMarshaller); } private DeliveryRequestAugmenter createAugmenter(Map<String, ConfigType> profiles) { - return new DeliveryRequestAugmenter(profiles, configUtil, validator); + return new DeliveryRequestAugmenter(profiles, configUtil, validator, mzsMarshaller); } private ConfigType createConfig(String url, Boolean performTnvz) { diff --git a/src/test/java/at/gv/egiz/moazs/ITEndToEndTest.java b/src/test/java/at/gv/egiz/moazs/ITEndToEndTest.java new file mode 100644 index 0000000..fd2e629 --- /dev/null +++ b/src/test/java/at/gv/egiz/moazs/ITEndToEndTest.java @@ -0,0 +1,259 @@ +package at.gv.egiz.moazs; + +import at.gv.egiz.moazs.client.ClientFactory; +import at.gv.egiz.moazs.repository.DeliveryRepository; +import at.gv.egiz.moazs.scheme.NotificationResponse; +import at.gv.egiz.moazs.scheme.RequestStatusResponse; +import at.gv.zustellung.app2mzs.xsd.DeliveryNotificationACKType; +import at.gv.zustellung.app2mzs.xsd.DeliveryResponseType; +import at.gv.zustellung.app2mzs.xsd.Mzs2AppPortType; +import at.gv.zustellung.msg.xsd.App2ZusePort; +import at.gv.zustellung.msg.xsd.DeliveryRequestStatusType; +import at.gv.zustellung.msg.xsd.DeliveryRequestType; +import at.gv.zustellung.tnvz.xsd.TNVZServicePort; +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.List; +import java.util.function.Consumer; + +import static at.gv.zustellung.app2mzs.xsd.DeliveryNotificationACKType.deliveryNotificationACKTypeBuilder; +import static at.gv.zustellung.app2mzs.xsd.persondata.IdentificationType.Value.valueBuilder; +import static at.gv.zustellung.app2mzs.xsd.persondata.IdentificationType.identificationTypeBuilder; +import static at.gv.zustellung.msg.xsd.DeliveryAnswerType.deliveryAnswerTypeBuilder; +import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.deliveryRequestStatusTypeBuilder; +import static java.net.http.HttpResponse.BodyHandlers.ofString; +import static org.apache.commons.io.FileUtils.readFileToString; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class ITEndToEndTest { + + private final static Logger log = LoggerFactory.getLogger(ITEndToEndTest.class); + public static final String GZ_WATERMARK = "my-secret-watermark-string"; + public static final String DELIVERY_SYSTEM = "http://localhost/url/to/msg/service"; + + @LocalServerPort + public int port; + private String mzsFrontendURL; + + private final String basePath = "src/test/resources/at/gv/egiz/moazs/ITEndToEndTest/"; + private static Mzs2AppPortType APP; + + @Before + public void setupFrontendURL() { + this.mzsFrontendURL = "http://localhost:" + port + "/services"; + } + + @TestConfiguration + public static class MockClientsAndSignatureVerificationConfig { + + + @Autowired + private DeliveryRepository repository; + + @Bean + @Primary + public Consumer<byte[]> signatureVerifier() { + return bytes -> {}; + } + + @Bean + @Primary + public ClientFactory mockClientFactory() { + var factory = mock(ClientFactory.class); + var tnvz = mockTnvz(); + var msg = mockMsg(); + APP = mockApp(); + when(factory.create(any(), same(TNVZServicePort.class))).thenReturn(tnvz); + when(factory.create(any(), same(App2ZusePort.class))).thenReturn(msg); + when(factory.create(any(), same(Mzs2AppPortType.class))).thenReturn(APP); + return factory; + } + + private Mzs2AppPortType mockApp() { + var app = mock(Mzs2AppPortType.class); + when(app.forwardStatus(any())).thenAnswer(i -> ack(i.getArgument(0))); + when(app.forwardNotification(any())).thenAnswer(i -> ack(i.getArgument(0))); + return app; + } + + private DeliveryNotificationACKType ack(DeliveryResponseType response) { + return deliveryNotificationACKTypeBuilder() + .withAppDeliveryID(response.getSuccess().getAppDeliveryID()) + .build(); + } + + private TNVZServicePort mockTnvz() { + var tnvz = mock(TNVZServicePort.class); + var value = valueBuilder().withId("id").withValue("value").build(); + var receiverId = identificationTypeBuilder() + .withValue(value).withId("id").withType("type").build(); + var tnvzHelperTest = new TnvzHelperTest(); + tnvzHelperTest.setup(); + var tnvzSuccess = tnvzHelperTest.tnvzSuccess(List.of("*/*"), receiverId); + + when(tnvz.queryPerson(any())).thenReturn(tnvzSuccess); + return tnvz; + } + + private App2ZusePort mockMsg() { + var msg = mock(App2ZusePort.class); + when(msg.delivery(any())).thenAnswer(i-> partialSuccess(i.getArgument(0))); + return msg; + } + + private DeliveryRequestStatusType partialSuccess(DeliveryRequestType request) { + + var appDeliveryID = request.getMetaData().getAppDeliveryID(); + var zsDeliveryID = "ZSDID-" + appDeliveryID; + var responseID = RequestStatusResponse.getResponseID(appDeliveryID); + var answer = deliveryAnswerTypeBuilder() + .withDeliverySystem(DELIVERY_SYSTEM) + .withAppDeliveryID(appDeliveryID) + .withZSDeliveryID(zsDeliveryID) + .withGZ(GZ_WATERMARK) + .build(); + repository.store(responseID, new byte[]{}); + return deliveryRequestStatusTypeBuilder() + .withPartialSuccess(answer) + .build(); + } + + } + + @Test + public void testHappyPath() throws IOException, InterruptedException { + + //prepare + var appDeliveryID = "delivery-request-id"; + var zsDeliveryID = "ZSDID-" + appDeliveryID; + var timestamp = ITMzsServiceTest.genTimeStamp().toXMLFormat(); + var saveSinkFolder = "target/tmp/ITEndToEndTestOut"; + delete(saveSinkFolder); + + //app sends delivery request to moazs and receives partial success + var partialSuccess = sendMzsDeliveryRequest("mzs-delivery-request.xml"); + assertThat(partialSuccess.statusCode()).isEqualTo(200); + assertThat(partialSuccess.body()).contains(List.of(GZ_WATERMARK, "PartialSuccess")); + + // zusemsg sends async success + var statusResponseID = RequestStatusResponse.getResponseID(appDeliveryID); + var msgStatus = formatFile("msg-delivery-request-status.xml", new String[]{ + DELIVERY_SYSTEM, zsDeliveryID, appDeliveryID, GZ_WATERMARK, timestamp + }); + sendMsgResponse(msgStatus); + Thread.sleep(100); + verify(APP).forwardStatus(any()); + assertStatusWrittenToFileSystem(saveSinkFolder, statusResponseID); + assertStatusWasLogged(); + + // zusemsg sends async notification + var notificationResponseID = NotificationResponse.getResponseID(appDeliveryID); + var notification = formatFile("msg-delivery-notification.xml", new String[]{ + DELIVERY_SYSTEM, zsDeliveryID, appDeliveryID, GZ_WATERMARK, timestamp, timestamp + }); + sendMsgResponse(notification); + Thread.sleep(100); + verify(APP).forwardNotification(any()); + assertStatusWrittenToFileSystem(saveSinkFolder, notificationResponseID); + assertStatusWasLogged(); + + } + + private void assertStatusWrittenToFileSystem(String folder, String pathSubString) { + var rootFolder = new File(folder); + Collection<File> files = FileUtils.listFiles(rootFolder, null, true); + + assertThat(rootFolder.exists()).isTrue(); + assertThat(rootFolder.isDirectory()).isTrue(); + assertThat(files).isNotEmpty(); + + long count = files.stream() + .map(File::getAbsolutePath) + .filter(path -> path.contains(pathSubString)) + .count(); + + assertThat(count).isEqualTo(2); + } + + private String readFile(File file) { + try { + return readFileToString(file, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void delete(String file) { + try { + FileUtils.deleteDirectory(new File(file)); + } catch (IOException e) { + log.warn("Could not delete {}", file); + } + } + + private void assertStatusWasLogged() { + //todo + } + + + private String formatFile(String templateFile, String... values) throws IOException { + var path = basePath + templateFile; + var templateString = FileUtils.readFileToString(new File(path), StandardCharsets.UTF_8); + return String.format(templateString, values); + } + + private HttpResponse<String> sendMsgResponse(String bodyString) throws IOException, InterruptedException { + + var body = HttpRequest.BodyPublishers.ofString(bodyString); + var client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build(); + var request = HttpRequest.newBuilder() + .uri(URI.create(mzsFrontendURL + "/msg/")) + .header("Content-Type", "text/xml;charset=UTF-8") + .header("SOAPAction", "\"\"") + .POST(body) + .build(); + + return client.send(request, ofString()); + + } + + private HttpResponse<String> sendMzsDeliveryRequest(String fileName) throws IOException, InterruptedException { + + var path = basePath + fileName; + var client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build(); + var request = HttpRequest.newBuilder() + .uri(URI.create(mzsFrontendURL + "/mzs/")) + .header("Content-Type", "text/xml;charset=UTF-8") + .header("SOAPAction", "\"\"") + .POST(HttpRequest.BodyPublishers.ofFile(Paths.get(path))) + .build(); + + return client.send(request, ofString()); + + } + +} diff --git a/src/test/java/at/gv/egiz/moazs/ITMzsServiceTest.java b/src/test/java/at/gv/egiz/moazs/ITMzsServiceTest.java index e9b4f70..3cf0362 100644 --- a/src/test/java/at/gv/egiz/moazs/ITMzsServiceTest.java +++ b/src/test/java/at/gv/egiz/moazs/ITMzsServiceTest.java @@ -2,12 +2,14 @@ package at.gv.egiz.moazs; import at.gv.egiz.moazs.repository.DeliveryRepository; import at.gv.egiz.moazs.scheme.RequestStatusResponse; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.test.context.junit4.SpringRunner; @@ -27,17 +29,24 @@ import java.util.function.Consumer; import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.Success.successBuilder; import static at.gv.zustellung.msg.xsd.DeliveryRequestStatusType.deliveryRequestStatusTypeBuilder; import static java.net.http.HttpClient.Version; -import static org.junit.Assert.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class ITMzsServiceTest { - private final String serviceUri = "http://localhost:8080/services/DeliveryRequest"; - private final String basePath = "src/test/resources/at/gv/egiz/moazs/ITMzsServiceTest/"; + @LocalServerPort + public int port; + private String serviceUri; + + @Before + public void setupServiceURI() { + this.serviceUri = "http://localhost:" + port + "/services/mzs"; + } + @TestConfiguration public static class TestConfig { @@ -64,50 +73,44 @@ public class ITMzsServiceTest { }; } - private XMLGregorianCalendar genTimeStamp() { - try { - return DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()); - } catch (DatatypeConfigurationException e) { - throw new RuntimeException("ups"); - } - } } @Test public void acceptValidDeliveryRequest() throws IOException, InterruptedException { var response = sendDeliveryRequestFile("validDeliveryRequest.soap"); - assertEquals(200, response.statusCode()); + assertThat(response.statusCode()).isEqualTo(200); + assertThat(response.body()).contains("valid-delivery-request-id"); } @Test public void rejectRequestWithoutSender() throws IOException, InterruptedException { var response = sendDeliveryRequestFile("missingSender.soap"); - assertEquals(500, response.statusCode()); + assertThat(response.statusCode()).isEqualTo(500); } @Test public void rejectBothProfileAndCorporateBody() throws IOException, InterruptedException { var response = sendDeliveryRequestFile("profileAndCorporateBody.soap"); - assertEquals(500, response.statusCode()); + assertThat(response.statusCode()).isEqualTo(500); } @Test public void rejectFormallyIncorrectDeliveryRequest() throws IOException, InterruptedException { var response = sendDeliveryRequestFile("formallyIncorrectDeliveryRequest.soap"); - assertEquals(500, response.statusCode()); + assertThat(response.statusCode()).isEqualTo(500); } @Test public void rejectRequestWithoutAppDeliveryID() throws IOException, InterruptedException { var response = sendDeliveryRequestFile("missingAppDeliveryId.soap"); - assertEquals(500, response.statusCode()); + assertThat(response.statusCode()).isEqualTo(500); } @Test public void rejectRequestWithoutMetaData() throws IOException, InterruptedException { var response = sendDeliveryRequestFile("missingMetaData.soap"); - assertEquals(500, response.statusCode()); + assertThat(response.statusCode()).isEqualTo(500); } private HttpResponse<String> sendDeliveryRequestFile(String fileName) throws IOException, InterruptedException { @@ -125,4 +128,13 @@ public class ITMzsServiceTest { } + public static XMLGregorianCalendar genTimeStamp() { + try { + return DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()); + } catch (DatatypeConfigurationException e) { + throw new RuntimeException("ups"); + } + + } + } diff --git a/src/test/java/at/gv/egiz/moazs/SOAPUtilsTest.java b/src/test/java/at/gv/egiz/moazs/SOAPUtilsTest.java index 31aa197..ff0060e 100644 --- a/src/test/java/at/gv/egiz/moazs/SOAPUtilsTest.java +++ b/src/test/java/at/gv/egiz/moazs/SOAPUtilsTest.java @@ -4,10 +4,8 @@ import at.gv.egiz.moazs.scheme.SOAPUtils; import org.junit.Before; import org.junit.Test; import org.w3c.dom.Element; -import org.xml.sax.SAXException; +import org.w3c.dom.Node; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; import java.nio.charset.StandardCharsets; import static org.assertj.core.api.Assertions.assertThat; @@ -25,39 +23,152 @@ public class SOAPUtilsTest { "est-id</ZSDeliveryID><AppDeliveryID>valid-delivery-request-id</AppDeliveryID><GZ>12345</GZ>" + "</PartialSuccess></DeliveryResponse></soap:Body></soap:Envelope>"; + + public static final String FORMATTED_MESSAGE = + "<soapenv:Envelope\n" + + " xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" + + " xmlns:msg=\"http://reference.e-government.gv.at/namespace/zustellung/msg/phase2/20181206#\">\n" + + " <soapenv:Body>\n" + + " <msg:DeliveryNotification>\n" + + " <msg:AppDeliveryID>formatted-adid</msg:AppDeliveryID>\n" + + " </msg:DeliveryNotification>\n" + + " </soapenv:Body>\n" + + "</soapenv:Envelope>\n"; + + public static final String CLUTTERED_MESSAGE = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<soapenv:Envelope " + + " xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n " + + " xmlns:msg=\"http://reference.e-government.gv.at/namespace/zustellung/msg/phase2/20181206#\">\n" + + " <soapenv:Body unexpected-attribute=\"unexpectedvalue\"> \n" + + " <msg:DeliveryNotification>\n" + + " <msg:AppDeliveryID attribute=\"some-value\"><element-that-got-lost />cluttered-adid</msg:AppDeliveryID>\n" + + " </msg:DeliveryNotification>\n" + + " </soapenv:Body>\n" + + "</soapenv:Envelope>\n"; + + private static final String MISSING_BODY_MESSAGE = + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><NotABodyTag></NotABodyTag></soap:Envelope>"; + + private static final String EMPTY_BODY_MESSAGE = + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body> </soap:Body></soap:Envelope>"; + + public static final String EMPTY_APP_DELIVERY_ID_MESSAGE = + "<soapenv:Envelope\n" + + " xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" + + " xmlns:msg=\"http://reference.e-government.gv.at/namespace/zustellung/msg/phase2/20181206#\">\n" + + " <soapenv:Body>\n" + + " <msg:DeliveryNotification>\n" + + " <msg:AppDeliveryID />\n" + + " </msg:DeliveryNotification>\n" + + " </soapenv:Body>\n" + + "</soapenv:Envelope>\n"; + + public static final String BLANK_APP_DELIVERY_ID_MESSAGE = + "<soapenv:Envelope\n" + + " xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" + + " xmlns:msg=\"http://reference.e-government.gv.at/namespace/zustellung/msg/phase2/20181206#\">\n" + + " <soapenv:Body>\n" + + " <msg:DeliveryNotification>\n" + + " <msg:AppDeliveryID> </msg:AppDeliveryID>\n" + + " </msg:DeliveryNotification>\n" + + " </soapenv:Body>\n" + + "</soapenv:Envelope>\n"; + @Before public void setup() { utils = new SOAPUtils(); } @Test - public void toDom() throws ParserConfigurationException, SAXException, IOException { - byte[] bytes = SOAP_MESSAGE.getBytes(StandardCharsets.UTF_8); + public void canParseSoapMessage() throws Exception { + parseAndCheckLocalName(SOAP_MESSAGE); + } + + @Test + public void canParseFormattedSoapMessage() throws Exception { + parseAndCheckLocalName(FORMATTED_MESSAGE); + } + + @Test + public void canParseClutteredSoapMessage() throws Exception { + parseAndCheckLocalName(CLUTTERED_MESSAGE); + } + private void parseAndCheckLocalName(String text) throws Exception { + byte[] bytes = text.getBytes(StandardCharsets.UTF_8); Element root = utils.toDOM(bytes); + assertThat(root.getLocalName()).isEqualTo("Envelope"); + } + + @Test + public void canUnwrapSoapMessage() throws Exception { + getFirstChildAndCheckLocalName(SOAP_MESSAGE, "DeliveryResponse"); + } - assertThat(root.getTagName()).isEqualTo("soap:Envelope"); + @Test + public void canUnwrapFormattedSoapMessage() throws Exception { + getFirstChildAndCheckLocalName(FORMATTED_MESSAGE, "DeliveryNotification"); } @Test - public void unwrapSoapEnvelope() throws ParserConfigurationException, SAXException, IOException { - byte[] bytes = SOAP_MESSAGE.getBytes(StandardCharsets.UTF_8); + public void canUnwrapClutteredSoapMessage() throws Exception { + getFirstChildAndCheckLocalName(CLUTTERED_MESSAGE, "DeliveryNotification"); + } + + @Test(expected=MoaZSException.class) + public void failUnwrapMissingBody() throws Exception { + getFirstChildAndCheckLocalName(MISSING_BODY_MESSAGE, ""); + } + + @Test(expected=MoaZSException.class) + public void failUnwrapEmptyBody() throws Exception { + getFirstChildAndCheckLocalName(EMPTY_BODY_MESSAGE, ""); + } + + private void getFirstChildAndCheckLocalName(String message, String expectedLocalNameOfChild) throws Exception { + byte[] bytes = message.getBytes(StandardCharsets.UTF_8); Element soapRoot = utils.toDOM(bytes); + Node child = utils.getChildElementOfSoapBody(soapRoot); + var actualLocalName = child.getLocalName(); + assertThat(actualLocalName).isEqualTo(expectedLocalNameOfChild); + } - byte[] unwrappedMessage = utils.unwrapSoapEnvelope(soapRoot); + @Test + public void getAppDeliveryIDFromSoapMessage() throws Exception { + getAppDeliveryIDAndCheck(SOAP_MESSAGE, "valid-delivery-request-id"); + } - Element deliveryResponseRoot = utils.toDOM(unwrappedMessage); - assertThat(deliveryResponseRoot.getTagName()).isEqualTo("DeliveryResponse"); + @Test + public void getAppDeliveryIDFromFormattedMessage() throws Exception { + getAppDeliveryIDAndCheck(FORMATTED_MESSAGE, "formatted-adid"); } @Test - public void getAppDeliveryID() throws ParserConfigurationException, SAXException, IOException { - byte[] bytes = SOAP_MESSAGE.getBytes(StandardCharsets.UTF_8); - Element soapRoot = utils.toDOM(bytes); + public void getAppDeliveryIDFromClutteredMessage() throws Exception { + getAppDeliveryIDAndCheck(CLUTTERED_MESSAGE, "cluttered-adid"); + } + + @Test(expected = MoaZSException.class) + public void failToRetrieveAppDeliveryIDWhenBodyIsMissing() throws Exception { + getAppDeliveryIDAndCheck(MISSING_BODY_MESSAGE, ""); + } - String appDeliveryID = utils.getAppDeliveryIDFrom(soapRoot); + @Test(expected = MoaZSException.class) + public void failToRetrieveEmptyAppDeliveryID() throws Exception { + getAppDeliveryIDAndCheck(EMPTY_APP_DELIVERY_ID_MESSAGE, ""); + } + + @Test(expected = MoaZSException.class) + public void failToRetrieveBlankAppDeliveryID() throws Exception { + getAppDeliveryIDAndCheck(BLANK_APP_DELIVERY_ID_MESSAGE, ""); + } - assertThat(appDeliveryID).isEqualTo("valid-delivery-request-id"); + private void getAppDeliveryIDAndCheck(String message, String expectedValue) throws Exception { + byte[] bytes = message.getBytes(StandardCharsets.UTF_8); + Element soapRoot = utils.toDOM(bytes); + String actualAppDeliveryID = utils.getAppDeliveryIDFrom(soapRoot); + assertThat(actualAppDeliveryID).isEqualTo(expectedValue); } } diff --git a/src/test/java/at/gv/egiz/moazs/TnvzHelperTest.java b/src/test/java/at/gv/egiz/moazs/TnvzHelperTest.java index 020e270..550f089 100644 --- a/src/test/java/at/gv/egiz/moazs/TnvzHelperTest.java +++ b/src/test/java/at/gv/egiz/moazs/TnvzHelperTest.java @@ -5,6 +5,8 @@ import at.gv.egiz.moazs.scheme.Mzs2MsgConverter; import at.gv.egiz.moazs.client.TnvzHelper; import at.gv.zustellung.app2mzs.xsd.DeliveryRequestType; import at.gv.zustellung.app2mzs.xsd.persondata.IdentificationType; +import at.gv.zustellung.msg.xsd.MetaData; +import at.gv.zustellung.msg.xsd.SystemComponentType; import at.gv.zustellung.tnvz.xsd.MimeTypeList; import at.gv.zustellung.tnvz.xsd.QueryPersonResponse; import at.gv.zustellung.tnvz.xsd.TNVZServicePort; @@ -20,11 +22,12 @@ import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Payload.payloadBu import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Receiver.receiverBuilder; import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.Sender.senderBuilder; import static at.gv.zustellung.app2mzs.xsd.DeliveryRequestType.deliveryRequestTypeBuilder; -import static at.gv.zustellung.app2mzs.xsd.TnvzMetaDataType.tnvzMetaDataTypeBuilder; import static at.gv.zustellung.app2mzs.xsd.persondata.CorporateBodyType.corporateBodyTypeBuilder; import static at.gv.zustellung.app2mzs.xsd.persondata.IdentificationType.Value.valueBuilder; import static at.gv.zustellung.app2mzs.xsd.persondata.IdentificationType.identificationTypeBuilder; import static at.gv.zustellung.msg.xsd.ErrorInfoType.errorInfoTypeBuilder; +import static at.gv.zustellung.msg.xsd.MetaData.metaDataBuilder; +import static at.gv.zustellung.msg.xsd.SystemComponentType.systemComponentTypeBuilder; import static at.gv.zustellung.tnvz.xsd.MimeTypeList.mimeTypeListBuilder; import static at.gv.zustellung.tnvz.xsd.PersonResultSuccessType.personResultSuccessTypeBuilder; import static at.gv.zustellung.tnvz.xsd.PersonResultType.Error.errorBuilder; @@ -119,14 +122,19 @@ public class TnvzHelperTest { .withIdentification(receiverId) .build(); - var metadata = tnvzMetaDataTypeBuilder() + var origin = systemComponentTypeBuilder() + .withParticipantID("ID") + .build(); + + var metadata = metaDataBuilder() + .withOrigin(origin) .build(); return deliveryRequestTypeBuilder() .withSender(sender) .withReceiver(receiver) - .withTnvzMetaData(metadata) .withPayload(payload(mzsMimeTypes)) + .withMetaData(metadata) .build(); } @@ -148,7 +156,7 @@ public class TnvzHelperTest { .collect(toList()); } - private QueryPersonResponse tnvzSuccess(List<String> mimeTypes, IdentificationType receiverId) { + public QueryPersonResponse tnvzSuccess(List<String> mimeTypes, IdentificationType receiverId) { var success = personResultSuccessTypeBuilder() .withMimeTypeList(setupMimeTypeList(mimeTypes)) |