diff --git a/README.md b/README.md index 41d0dcc..36e971d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ A common example is using Wiremock 3.x with Java 1.8. The module is compatible with the following WireMock versions: - WireMock (aka WireMock Java) `2.0.0` and above -- WireMock (aka WireMock Java) `3.0.0` beta versions. +- WireMock (aka WireMock Java) `3.x` versions. Note that the official image for WireMock 3 is yet to be released and verified ([issue #59](https://github.com/wiremock/wiremock-testcontainers-java/issues/59)) Other WireMock implementations may work but have not been tested yet. diff --git a/pom.xml b/pom.xml index c248b07..3e149f0 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ 1.8 ${java.version} ${java.version} - 2.35.0 + 3.5.4 1.19.8 5.10.2 3.26.3 @@ -178,6 +178,11 @@ 0.4.1 jar-with-dependencies + + org.wiremock + wiremock + ${wiremock.version} + org.wiremock wiremock-webhooks-extension diff --git a/src/main/java/org/wiremock/integrations/testcontainers/WireMockContainer.java b/src/main/java/org/wiremock/integrations/testcontainers/WireMockContainer.java index cbcb9f7..ccd7cb5 100644 --- a/src/main/java/org/wiremock/integrations/testcontainers/WireMockContainer.java +++ b/src/main/java/org/wiremock/integrations/testcontainers/WireMockContainer.java @@ -47,11 +47,15 @@ public class WireMockContainer extends GenericContainer { public static final String OFFICIAL_IMAGE_NAME = "wiremock/wiremock"; - private static final String WIREMOCK_2_LATEST_TAG = "2.35.0"; + private static final String WIREMOCK_2_LATEST_TAG = "2.35.0-1"; + private static final String WIREMOCK_3_LATEST_TAG = "3.5.4"; /*package*/ static final String WIREMOCK_2_MINIMUM_SUPPORTED_VERSION = "2.0.0"; - static final String WIREMOCK_HEALTH_CHECK_SUPPORT_MINIMUM_VERSION = "3.0.0-1"; + /** + * @deprecated Not really guaranteed to be latest. Will be reworked + */ + @Deprecated public static final DockerImageName WIREMOCK_2_LATEST = DockerImageName.parse(OFFICIAL_IMAGE_NAME).withTag(WIREMOCK_2_LATEST_TAG); diff --git a/src/test/java/org/wiremock/integrations/testcontainers/TestConfig.java b/src/test/java/org/wiremock/integrations/testcontainers/TestConfig.java new file mode 100644 index 0000000..de2bcf0 --- /dev/null +++ b/src/test/java/org/wiremock/integrations/testcontainers/TestConfig.java @@ -0,0 +1,17 @@ +package org.wiremock.integrations.testcontainers; + +import org.testcontainers.utility.DockerImageName; + +public class TestConfig { + + private static final String DEFAULT_TEST_TAG = + System.getProperty("wiremock.testcontainer.defaultTag", "3.5.4"); + private static final String WIREMOCK_2_TEST_TAG = + System.getProperty("wiremock.testcontainer.wiremock2Tag", "2.35.1-1"); + + public static final DockerImageName WIREMOCK_DEFAULT_IMAGE = + DockerImageName.parse(WireMockContainer.OFFICIAL_IMAGE_NAME).withTag(DEFAULT_TEST_TAG); + + public static final DockerImageName WIREMOCK_2_IMAGE = + DockerImageName.parse(WireMockContainer.OFFICIAL_IMAGE_NAME).withTag(WIREMOCK_2_TEST_TAG); +} diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerBannerTest.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerBannerTest.java index a2d3d2d..14647e1 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerBannerTest.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerBannerTest.java @@ -21,7 +21,7 @@ class WireMockContainerBannerTest { - WireMockContainer wireMockContainer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST); + WireMockContainer wireMockContainer = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE); @Test void bannerIsByDefaultDisabled() { diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionTest.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionTest.java index 4504510..7a6e4e4 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionTest.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionTest.java @@ -40,7 +40,7 @@ class WireMockContainerExtensionTest { private static final Logger LOGGER = LoggerFactory.getLogger(WireMockContainerExtensionTest.class); @Container - WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) + WireMockContainer wiremockServer = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE) .withLogConsumer(new Slf4jLogConsumer(LOGGER)) .withStartupTimeout(Duration.ofSeconds(60)) .withMapping("json-body-transformer", WireMockContainerExtensionTest.class, "json-body-transformer.json") diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsCombinationTest.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsCombinationTest.java index 7d85451..e11e236 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsCombinationTest.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsCombinationTest.java @@ -39,12 +39,12 @@ class WireMockContainerExtensionsCombinationTest { private static final Logger LOGGER = LoggerFactory.getLogger(WireMockContainerExtensionsCombinationTest.class); @Container - WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) + WireMockContainer wiremockServer = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE) .withLogConsumer(new Slf4jLogConsumer(LOGGER)) .withMapping("json-body-transformer", WireMockContainerExtensionsCombinationTest.class, "json-body-transformer.json") .withExtensions("Webhook", Collections.singleton("org.wiremock.webhooks.Webhooks"), - Collections.singleton(Paths.get("target", "test-wiremock-extension", "wiremock-webhooks-extension-2.35.0.jar").toFile())) + Collections.singleton(Paths.get("target", "test-wiremock-extension", "wiremock-webhooks-extension-3.5.4.jar").toFile())) .withExtensions("JSON Body Transformer", Collections.singleton("com.ninecookies.wiremock.extensions.JsonBodyTransformer"), Collections.singleton(Paths.get("target", "test-wiremock-extension", "wiremock-extensions-0.4.1-jar-with-dependencies.jar").toFile())); diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerJunit4Test.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerJunit4Test.java index 8397d8b..2e50bf2 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerJunit4Test.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerJunit4Test.java @@ -25,7 +25,7 @@ public class WireMockContainerJunit4Test { @Rule - public WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) + public WireMockContainer wiremockServer = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE) .withMapping("hello", WireMockContainerTest.class, "hello-world.json") .withMapping("hello-resource", WireMockContainerTest.class, "hello-world-resource.json") .withFileFromResource("hello-world-resource-response.xml", WireMockContainerTest.class, "hello-world-resource-response.xml"); diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerTest.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerTest.java index 2ede03d..5963619 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerTest.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerTest.java @@ -29,7 +29,7 @@ class WireMockContainerTest { @Container - WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) + WireMockContainer wiremockServer = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE) .withMapping("hello", WireMockContainerTest.class, "hello-world.json") .withMapping("hello-resource", WireMockContainerTest.class, "hello-world-resource.json") .withFileFromResource("hello-world-resource-response.xml", WireMockContainerTest.class, diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerUnitTest.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerUnitTest.java index f1c7cd4..e35cc9c 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerUnitTest.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerUnitTest.java @@ -11,7 +11,7 @@ public class WireMockContainerUnitTest { @Test public void shouldInitWithDefault() { - WireMockContainer container = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST); + WireMockContainer container = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE); } @Test diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerWebhooksTest.java similarity index 88% rename from src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest.java rename to src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerWebhooksTest.java index ba54e21..a39b665 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerWebhooksTest.java @@ -47,25 +47,21 @@ * @see Testcontainers Networking */ @Testcontainers -class WireMockContainerExtensionsWebhookTest { +class WireMockContainerWebhooksTest { - private static final Logger LOGGER = LoggerFactory.getLogger(WireMockContainerExtensionsWebhookTest.class); + private static final Logger LOGGER = LoggerFactory.getLogger(WireMockContainerWebhooksTest.class); private static final String WIREMOCK_PATH = "/wiremock/callback-trigger"; private static final String APPLICATION_PATH = "/application/callback-receiver"; TestHttpServer applicationServer = TestHttpServer.newInstance(); @Container - WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) + WireMockContainer wiremockServer = new WireMockContainer(TestConfig.WIREMOCK_DEFAULT_IMAGE) .withLogConsumer(new Slf4jLogConsumer(LOGGER)) .withCliArg("--global-response-templating") - .withMapping("webhook-callback-template", WireMockContainerExtensionsWebhookTest.class, "webhook-callback-template.json") - .withExtensions("Webhook", - Collections.singleton("org.wiremock.webhooks.Webhooks"), - Collections.singleton(Paths.get("target", "test-wiremock-extension", "wiremock-webhooks-extension-2.35.0.jar").toFile())) + .withMapping("webhook-callback-template", WireMockContainerWebhooksTest.class, "webhook-callback-template.json") .withAccessToHost(true); // Force the host access mechanism - @Test void callbackUsingJsonStub() throws Exception { // given diff --git a/src/test/java/org/wiremock/integrations/testcontainers/wiremock2/WebhooksExtensionTest.java b/src/test/java/org/wiremock/integrations/testcontainers/wiremock2/WebhooksExtensionTest.java new file mode 100644 index 0000000..eb047b6 --- /dev/null +++ b/src/test/java/org/wiremock/integrations/testcontainers/wiremock2/WebhooksExtensionTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2023 WireMock Inc, Oleg Nenashev and all project contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wiremock.integrations.testcontainers.wiremock2; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.testcontainers.Testcontainers.exposeHostPorts; +import static org.testcontainers.shaded.org.awaitility.Awaitility.await; + +import java.nio.file.Paths; +import java.time.Duration; +import java.util.Collections; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.wiremock.integrations.testcontainers.TestConfig; +import org.wiremock.integrations.testcontainers.WireMockContainer; +import org.wiremock.integrations.testcontainers.testsupport.http.HttpResponse; +import org.wiremock.integrations.testcontainers.testsupport.http.TestHttpClient; +import org.wiremock.integrations.testcontainers.testsupport.http.TestHttpServer; + +/** + * Tests the WireMock Webhook extension and TestContainers Networking + * For this type of tests we should use following steps: + *

+ * Use {@link GenericContainer#withAccessToHost(boolean)} to force the host access mechanism + *

+ * Use {@link org.testcontainers.Testcontainers#exposeHostPorts(int...)} to expose host machine ports to containers + *

+ * Use {@link GenericContainer#INTERNAL_HOST_HOSTNAME} to calculate hostname for callback + * + * @see Testcontainers Networking + */ +@Testcontainers +class WebhooksExtensionTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(WebhooksExtensionTest.class); + private static final String WIREMOCK_PATH = "/wiremock/callback-trigger"; + private static final String APPLICATION_PATH = "/application/callback-receiver"; + + + TestHttpServer applicationServer = TestHttpServer.newInstance(); + @Container + WireMockContainer wiremockServer = new WireMockContainer(TestConfig.WIREMOCK_2_IMAGE) + .withLogConsumer(new Slf4jLogConsumer(LOGGER)) + .withCliArg("--global-response-templating") + .withMapping("webhook-callback-template", WebhooksExtensionTest.class, "webhook-callback-template.json") + .withExtensions("Webhooks", + Collections.singleton("org.wiremock.webhooks.Webhooks"), + Collections.singleton(Paths.get("target", "test-wiremock-extension", "wiremock-webhooks-extension-2.35.0.jar").toFile())) + .withAccessToHost(true); // Force the host access mechanism + + @Test + void callbackUsingJsonStub() throws Exception { + // given + exposeHostPorts(applicationServer.getPort()); // Exposing host ports to the container + + String wiremockUrl = wiremockServer.getUrl(WIREMOCK_PATH); + String applicationCallbackUrl = String.format("http://%s:%d%s", GenericContainer.INTERNAL_HOST_HOSTNAME, applicationServer.getPort(), APPLICATION_PATH); + + // when + HttpResponse response = new TestHttpClient().post( + wiremockUrl, + "{\"callbackMethod\": \"PUT\", \"callbackUrl\": \"" + applicationCallbackUrl + "\"}" + ); + + // then + assertThat(response).as("Wiremock Response").isNotNull().satisfies(it -> { + assertThat(it.getStatusCode()).as("Wiremock Response Status").isEqualTo(200); + assertThat(it.getBody()).as("Wiremock Response Body") + .contains("Please wait callback") + .contains("PUT") + .contains(applicationCallbackUrl); + }); + + await().atMost(Duration.ofMillis(5000)).untilAsserted(() -> { + assertThat(applicationServer.getRecordedRequests()).as("Received Callback") + .hasSize(1) + .first().usingRecursiveComparison() + .isEqualTo(new TestHttpServer.RecordedRequest("PUT", APPLICATION_PATH, "Async processing Finished")); + }); + } + +} diff --git a/src/test/java/org/wiremock/integrations/testcontainers/wiremock2/WireMockContainerExtensionsCombinationTest.java b/src/test/java/org/wiremock/integrations/testcontainers/wiremock2/WireMockContainerExtensionsCombinationTest.java new file mode 100644 index 0000000..1bc30ca --- /dev/null +++ b/src/test/java/org/wiremock/integrations/testcontainers/wiremock2/WireMockContainerExtensionsCombinationTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2023 WireMock Inc, Oleg Nenashev and all project contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wiremock.integrations.testcontainers.wiremock2; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.wiremock.integrations.testcontainers.TestConfig; +import org.wiremock.integrations.testcontainers.WireMockContainer; +import org.wiremock.integrations.testcontainers.testsupport.http.HttpResponse; +import org.wiremock.integrations.testcontainers.testsupport.http.TestHttpClient; + +import java.nio.file.Paths; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests the WireMock extension loading. + * It uses multiple external Jars supplied by the Maven Dependency Plugin. + */ +@Testcontainers +class WireMockContainerExtensionsCombinationTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(WireMockContainerExtensionsCombinationTest.class); + + @Container + WireMockContainer wiremockServer = new WireMockContainer(TestConfig.WIREMOCK_2_IMAGE) + .withLogConsumer(new Slf4jLogConsumer(LOGGER)) + .withMapping("json-body-transformer", WireMockContainerExtensionsCombinationTest.class, "json-body-transformer.json") + .withExtensions("Webhook", + Collections.singleton("org.wiremock.webhooks.Webhooks"), + Collections.singleton(Paths.get("target", "test-wiremock-extension", "wiremock-webhooks-extension-2.35.0.jar").toFile())) + .withExtensions("JSON Body Transformer", + Collections.singleton("com.ninecookies.wiremock.extensions.JsonBodyTransformer"), + Collections.singleton(Paths.get("target", "test-wiremock-extension", "wiremock-extensions-0.4.1-jar-with-dependencies.jar").toFile())); + + @Test + void testJSONBodyTransformer() throws Exception { + // given + String url = wiremockServer.getUrl("/json-body-transformer"); + String body = "{\"name\":\"John Doe\"}"; + + // when + HttpResponse response = new TestHttpClient().post(url, body); + + // then + assertThat(response.getBody()) + .as("Wrong response body") + .contains("Hello, John Doe!"); + } +} diff --git a/src/test/resources/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest/webhook-callback-template.json b/src/test/resources/org/wiremock/integrations/testcontainers/WireMockContainerWebhooksTest/webhook-callback-template.json similarity index 100% rename from src/test/resources/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest/webhook-callback-template.json rename to src/test/resources/org/wiremock/integrations/testcontainers/WireMockContainerWebhooksTest/webhook-callback-template.json diff --git a/src/test/resources/org/wiremock/integrations/testcontainers/wiremock2/WebhooksExtensionTest/webhook-callback-template.json b/src/test/resources/org/wiremock/integrations/testcontainers/wiremock2/WebhooksExtensionTest/webhook-callback-template.json new file mode 100644 index 0000000..1e509ea --- /dev/null +++ b/src/test/resources/org/wiremock/integrations/testcontainers/wiremock2/WebhooksExtensionTest/webhook-callback-template.json @@ -0,0 +1,31 @@ +{ + "request": { + "method": "POST", + "urlPath": "/wiremock/callback-trigger" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "jsonBody": { + "message": "Please wait callback", + "method": "{{jsonPath request.body '$.callbackMethod'}}", + "url": "{{jsonPath request.body '$.callbackUrl'}}" + } + }, + "postServeActions": [ + { + "name": "webhook", + "parameters": { + "method": "{{jsonPath originalRequest.body '$.callbackMethod'}}", + "url": "{{jsonPath originalRequest.body '$.callbackUrl'}}", + "body": "Async processing Finished", + "delay": { + "type": "fixed", + "milliseconds": 1000 + } + } + } + ] +} \ No newline at end of file diff --git a/src/test/resources/org/wiremock/integrations/testcontainers/wiremock2/WireMockContainerExtensionsCombinationTest/json-body-transformer.json b/src/test/resources/org/wiremock/integrations/testcontainers/wiremock2/WireMockContainerExtensionsCombinationTest/json-body-transformer.json new file mode 100644 index 0000000..2874cec --- /dev/null +++ b/src/test/resources/org/wiremock/integrations/testcontainers/wiremock2/WireMockContainerExtensionsCombinationTest/json-body-transformer.json @@ -0,0 +1,16 @@ +{ + "request": { + "method": "POST", + "url": "/json-body-transformer" + }, + "response": { + "status": 201, + "headers": { + "content-type": "application/json" + }, + "jsonBody": { + "message": "Hello, $(name)!" + }, + "transformers" : ["json-body-transformer"] + } +} \ No newline at end of file