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 | |
| 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')
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)) | 
