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

KOP-3126 Try out wiremock

parent 54b79d5b
Branches
Tags
No related merge requests found
Pipeline #2283 failed
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
<cxf-xjc.version>4.0.0</cxf-xjc.version> <cxf-xjc.version>4.0.0</cxf-xjc.version>
<jsr305.version>3.0.2</jsr305.version> <jsr305.version>3.0.2</jsr305.version>
<wiremock.version>3.12.1</wiremock.version>
<!-- Build settings --> <!-- Build settings -->
<timestamp>${maven.build.timestamp}</timestamp> <timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd'T'HHmmss</maven.build.timestamp.format> <maven.build.timestamp.format>yyyy-MM-dd'T'HHmmss</maven.build.timestamp.format>
...@@ -102,10 +104,6 @@ ...@@ -102,10 +104,6 @@
</dependency> </dependency>
<!-- Test --> <!-- Test -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.assertj</groupId> <groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId> <artifactId>assertj-core</artifactId>
...@@ -141,6 +139,11 @@ ...@@ -141,6 +139,11 @@
<artifactId>snakeyaml</artifactId> <artifactId>snakeyaml</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<version>${wiremock.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package de.ozgcloud.xta.client;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.*;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import com.github.tomakehurst.wiremock.WireMockServer;
import de.ozgcloud.xta.client.config.XtaClientConfig;
import de.ozgcloud.xta.client.core.WrappedXtaService;
import de.ozgcloud.xta.client.core.WrappedXtaServiceFactory;
import de.ozgcloud.xta.client.factory.XtaMockServerResponseTestFactory;
import de.ozgcloud.xta.client.model.XtaIdentifier;
import lombok.SneakyThrows;
class XtaSchemaValidationITCase {
WrappedXtaService xtaService;
private static final String XTA_MOCK_SERVER_URL_BASE = "https://localhost:8089";
private static final String XTA_MOCK_SERVER_URL_PATH = "/MB_XTA-WS/XTA210";
private static final String XTA_MOCK_SERVER_URL = XTA_MOCK_SERVER_URL_BASE + XTA_MOCK_SERVER_URL_PATH;
WireMockServer wireMockServer;
@BeforeEach
@SneakyThrows
void setup() {
wireMockServer = new WireMockServer(options().port(8089));
wireMockServer.start();
xtaService = WrappedXtaServiceFactory.from(XtaClientConfig.builder()
.schemaValidation(true)
.logSoapResponses(true)
.logSoapRequests(true)
.managementServiceUrl(XTA_MOCK_SERVER_URL + "managementPort.svc")
.sendServiceUrl(XTA_MOCK_SERVER_URL + "sendPort.svc")
.msgBoxServiceUrl(XTA_MOCK_SERVER_URL + "msgBoxPort.svc")
.build()).create();
}
@AfterEach
void tearDown() {
wireMockServer.stop();
}
@DisplayName("should throw UnmarshallException on bad response")
@Test
@SneakyThrows
void shouldThrowUnmarshallExceptionOnBadResponse() {
stubFor(post(XTA_MOCK_SERVER_URL_PATH + "msgBoxPort.svc")
.willReturn(
XtaMockServerResponseTestFactory.createGetMessageResponse(
"2f45a9e9-ed40-4e14-a082-de0d063e56e7_Geschaeftsgang.Geschaeftsgang.0201.zip")));
var message = xtaService.getMessage("urn:de:xta:messageid:dataport_xta_210:db6ad282-c510-4154-a167-daaa8b9f345a", XtaIdentifier.builder()
.value("afmsh:ozg-cloud-stage-Utopia")
.build());
assertThat(message).isNotNull();
}
@DisplayName("should not fail on good response")
@Test
void shouldNotFailOnGoodResponse() {
}
}
...@@ -22,7 +22,6 @@ import jakarta.mail.util.ByteArrayDataSource; ...@@ -22,7 +22,6 @@ import jakarta.mail.util.ByteArrayDataSource;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import org.apache.commons.codec.Resources; import org.apache.commons.codec.Resources;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
...@@ -106,15 +105,14 @@ public class XtaMessageExampleLoader { ...@@ -106,15 +105,14 @@ public class XtaMessageExampleLoader {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static Map<String, Object> getChild(Map<String, Object> parent, String key) { private static Map<String, Object> getChild(Map<String, Object> parent, String key) {
return Objects.requireNonNull((Map<String, Object>) MapUtils.getMap(parent, key), "Missing key: %s".formatted(key)); return Objects.requireNonNull((Map<String, Object>) parent.get(key), "Missing key: %s".formatted(key));
} }
private static XtaFile mapXtaFile( private static XtaFile mapXtaFile(
Map<String, Object> messageFile, Map<String, Object> messageFile,
String resourcePrefix, String resourcePrefix,
MessageFileProcessor messageFileProcessor) { MessageFileProcessor messageFileProcessor) {
Function<String, String> getString = key -> Objects.requireNonNull( Function<String, String> getString = key -> getMapString(messageFile, key);
MapUtils.getString(messageFile, key), "[Failed mapping for %s] Missing key: %s".formatted(resourcePrefix, key));
var name = getString.apply("name"); var name = getString.apply("name");
var path = getMessageResourcePath(resourcePrefix, name); var path = getMessageResourcePath(resourcePrefix, name);
...@@ -135,9 +133,16 @@ public class XtaMessageExampleLoader { ...@@ -135,9 +133,16 @@ public class XtaMessageExampleLoader {
.toList(); .toList();
} }
private static String getMapString(Map<String, Object> map, String key) {
return Optional.ofNullable(map.get(key))
.filter(String.class::isInstance)
.map(String.class::cast)
.orElseThrow(() -> new IllegalArgumentException("Missing key: %s".formatted(key)));
}
private static XtaMessageMetaData mapXtaMessageMetadata(Map<String, Object> metaData, MessageExampleConfig config) { private static XtaMessageMetaData mapXtaMessageMetadata(Map<String, Object> metaData, MessageExampleConfig config) {
Function<String, String> getString = key -> Objects.requireNonNull( Function<String, String> getString = key -> Objects.requireNonNull(
MapUtils.getString(metaData, key), "metaData key missing: %s".formatted(key)); getMapString(metaData, key), "metaData key missing: %s".formatted(key));
return XtaMessageMetaData.builder() return XtaMessageMetaData.builder()
.service(getString.apply("service")) .service(getString.apply("service"))
.businessScenarioCode(getString.apply("businessScenarioCode")) .businessScenarioCode(getString.apply("businessScenarioCode"))
...@@ -146,7 +151,7 @@ public class XtaMessageExampleLoader { ...@@ -146,7 +151,7 @@ public class XtaMessageExampleLoader {
.messageTypeCode(getString.apply("messageTypeCode")) .messageTypeCode(getString.apply("messageTypeCode"))
.messageTypePayloadSchema(getString.apply("messageTypePayloadSchema")) .messageTypePayloadSchema(getString.apply("messageTypePayloadSchema"))
.messageId(getIfConfigNull( .messageId(getIfConfigNull(
config.messageId, () -> MapUtils.getString(metaData, "messageId"))) config.messageId, () -> getMapString(metaData, "messageId")))
.authorIdentifier(getIfConfigNull( .authorIdentifier(getIfConfigNull(
config.author, config.author,
() -> mapIdentifier(getChild(metaData, "authorIdentifier")))) () -> mapIdentifier(getChild(metaData, "authorIdentifier"))))
......
package de.ozgcloud.xta.client.factory;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
import de.ozgcloud.common.test.TestUtils;
public class XtaMockServerResponseTestFactory {
private static final String UUID_BOUNDARY = "uuid:4403149a-87eb-4bb4-b885-472816010e04+id=12707";
// The MIME Multipart/Related Content-type (See https://www.ietf.org/rfc/rfc2387.txt)
private static final String MULTIPART_RELATED_CONTENT_TYPE = "multipart/related; type=\"application/xop+xml\";start=\"<http://tempuri.org/0>\";boundary=\"%s\";start-info=\"application/soap+xml\"".formatted(
UUID_BOUNDARY);
private static final String INCLUDE_URL = "http://tempuri.org/1/638485294711394846";
private static final Map<String, String> ENVELOPE_HEADERS = Map.of(
"Content-ID", "<http://tempuri.org/0>",
"Content-Transfer-Encoding", "8bit",
"Content-Type", "application/xop+xml;charset=utf-8;type=\"application/soap+xml\""
);
private static String generateMessageID(String xtaAttachmentFileName) {
return "urn:de:xta:messageid:dataport_xta_210:%s".formatted(UUID.fromString(xtaAttachmentFileName).toString());
}
public static ResponseDefinitionBuilder createEmptyGetStatusListResponse() {
var envelopeXMLString = TestUtils.loadTextFile(
"mock-responses/getStatusList/envelope.template.xml",
"0",
""
);
var body = combineParts(
createPart(
ENVELOPE_HEADERS,
envelopeXMLString
)
);
return ok()
.withHeader("Content-Type", MULTIPART_RELATED_CONTENT_TYPE)
.withBody(body);
}
public static ResponseDefinitionBuilder createGetStatusListResponse(List<String> xtaAttachmentFileNames) {
var messageMetaDataEntriesString = xtaAttachmentFileNames.stream()
.map(XtaMockServerResponseTestFactory::createMessageMetadataXml)
.collect(Collectors.joining());
var envelopeXMLString = TestUtils.loadTextFile(
"mock-responses/getStatusList/envelope.template.xml",
String.valueOf(xtaAttachmentFileNames.size()),
messageMetaDataEntriesString
);
var body = combineParts(
createPart(
ENVELOPE_HEADERS,
envelopeXMLString
)
);
return ok()
.withHeader("Content-Type", MULTIPART_RELATED_CONTENT_TYPE)
.withBody(body);
}
public static ResponseDefinitionBuilder createGetMessageResponse(String xtaAttachmentFileName) {
var metadataMessageXml = createMessageMetadataXml(xtaAttachmentFileName);
var envelopeXMLString = TestUtils.loadTextFile(
"mock-responses/getMessage/stage-example/envelope.template.xml",
generateMessageID(xtaAttachmentFileName),
metadataMessageXml,
xtaAttachmentFileName,
getFileSize(getAttachmentFilePath(xtaAttachmentFileName)),
INCLUDE_URL
);
var body = combineParts(
createPart(
ENVELOPE_HEADERS,
envelopeXMLString
),
createPart(
Map.of(
"Content-ID", "<%s>".formatted(INCLUDE_URL),
"Content-Transfer-Encoding", "base64",
"Content-Type", "application/octet-stream"
),
loadFileAsBase64(
getAttachmentFilePath(xtaAttachmentFileName)
)
)
);
return ok()
.withHeader("Content-Type", MULTIPART_RELATED_CONTENT_TYPE)
.withBody(body);
}
private static String createMessageMetadataXml(String xtaAttachmentFileName) {
return TestUtils.loadTextFile(
"mock-responses/getStatusList/MessageMetaData/stage-example/metadata.template.xml",
generateMessageID(xtaAttachmentFileName),
getFileSize(getAttachmentFilePath(xtaAttachmentFileName))
);
}
private static String getFileSize(String filePath) {
try (var inputStream = TestUtils.loadFile(filePath)) {
return String.valueOf(inputStream.readAllBytes().length);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static String getAttachmentFilePath(String xtaAttachmentFileName) {
return "mock-responses/getMessage/stage-example/%s".formatted(xtaAttachmentFileName);
}
private static String loadFileAsBase64(String fileName) {
try (var attachmentFile = TestUtils.loadFile(fileName)) {
return new String(Base64.getEncoder().encode(attachmentFile.readAllBytes()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static String combineParts(String... parts) {
return Stream.concat(
Arrays.stream(parts).map(part -> "--%s\n%s\n".formatted(UUID_BOUNDARY, part)),
Stream.of("--%s--".formatted(UUID_BOUNDARY)))
.collect(Collectors.joining());
}
private static String createPart(Map<String, String> headers, String content) {
return String.join("\n",
headers.entrySet().stream().map(kv -> "%s: %s\n".formatted(kv.getKey(), kv.getValue())).collect(Collectors.joining()), content);
}
}
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.osci.eu/ws/2008/05/transport/urn/messageTypes/MsgBoxFetchRequest</a:Action>
<h:MsgBoxResponse MsgBoxRequestID="%s" xmlns:h="http://www.osci.eu/ws/2008/05/transport" xmlns="http://www.osci.eu/ws/2008/05/transport" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ItemsPending>0</ItemsPending>
</h:MsgBoxResponse>
%s
<a:RelatesTo>urn:uuid:a0c6d23f-4fbf-49fd-b1f4-b5187d5170f0</a:RelatesTo>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GenericContentContainer xmlns="http://xoev.de/transport/xta/211">
<ContentContainer>
<Message contentType="application/zip" filename="%s" id="2f45a9e9-ed40-4e14-a082-de0d063e56e7" size="%s">
<xop:Include href="%s" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
</Message>
</ContentContainer>
</GenericContentContainer>
</s:Body>
</s:Envelope>
\ No newline at end of file
<h:MessageMetaData xmlns:h="http://www.osci.eu/ws/2014/10/transport" xmlns="http://www.osci.eu/ws/2014/10/transport">
<DeliveryAttributes>
<Origin>2025-03-28T02:24:29.176</Origin>
<Delivery>2025-03-28T02:24:30.883</Delivery>
<InitialFetch>2025-04-01T10:01:16.1</InitialFetch>
<Reception>2025-04-01T15:03:22.61</Reception>
</DeliveryAttributes>
<Originators>
<Author>
<Identifier type="xoev">afmsh:WebMethod_Online-Dienste</Identifier>
</Author>
</Originators>
<Destinations>
<Reader>
<Identifier type="xoev">afmsh:ozg-cloud-stage-Utopia</Identifier>
</Reader>
</Destinations>
<MsgIdentification>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">%s</MessageID>
</MsgIdentification>
<Qualifier>
<Service>urn:xdomea:AFM</Service>
<BusinessScenario>
<Defined listURI="urn:de:dataport:codeliste:business.scenario" listVersionID="1">
<code xmlns="">AFM_DATA</code>
</Defined>
</BusinessScenario>
<MessageType listURI="urn:de:payloadSchema:elementName" listVersionID="1.0" payloadSchema="http://www.xdomea.de/V2.0.1">
<code xmlns="">Geschaeftsgang.Geschaeftsgang.0201</code>
</MessageType>
</Qualifier>
<MsgSize>%s</MsgSize>
</h:MessageMetaData>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment