diff --git a/README.md b/README.md index 882eab3..513b5f1 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,20 @@ within your unit test, based on [WireMock Docker](https://github.com/wiremock/wi While you can run [WireMock Java](https://github.com/wiremock/wiremock) with the same result for the most of the use-cases, -it might be helpful to isolate JVMs or to run on +it might be helpful to isolate JVMs or to run on Java versions and platforms not supported by WireMock. A common example is using Wiremock 3.x with Java 1.8. +## Compatibility + +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 + +Other WireMock implementations may work but have not been tested yet. +Please feel free to contribute the integration tests and compatibility layers! + ## Usage ### Importing the dependency @@ -49,7 +59,7 @@ import static org.assertj.core.api.Assertions.assertThat; class WireMockContainerJunit5Test { @Container - WireMockContainer wiremockServer = new WireMockContainer("2.35.0") + WireMockContainer wiremockServer = new WireMockContainer("wiremock/wiremock:2.35.0") .withMapping("hello", WireMockContainerJunit5Test.class, "hello-world.json"); @Test @@ -84,7 +94,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class WireMockContainerJunit4Test { @Rule - public WireMockContainer wiremockServer = new WireMockContainer("2.35.0") + public WireMockContainer wiremockServer = new WireMockContainer("wiremock/wiremock:2.35.0") .withMapping("hello", WireMockContainerJunit4Test.class, "hello-world.json"); @Test @@ -191,7 +201,7 @@ import static org.assertj.core.api.Assertions.assertThat; class WireMockContainerExtensionJunit5Test { @Container - WireMockContainer wiremockServer = new WireMockContainer("2.35.0") + WireMockContainer wiremockServer = new WireMockContainer("wiremock/wiremock:2.35.0") .withMapping("json-body-transformer", WireMockContainerExtensionJunit5Test.class, "json-body-transformer.json") .withExtension("JSON Body Transformer", Collections.singleton("com.ninecookies.wiremock.extensions.JsonBodyTransformer"), @@ -232,7 +242,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class WireMockContainerExtensionJunit4Test { @Rule - public WireMockContainer wiremockServer = new WireMockContainer("2.35.0") + public WireMockContainer wiremockServer = new WireMockContainer("wiremock/wiremock:2.35.0") .withMapping("json-body-transformer", WireMockContainerExtensionJunit4Test.class, "json-body-transformer.json") .withExtension("JSON Body Transformer", Collections.singleton("com.ninecookies.wiremock.extensions.JsonBodyTransformer"), diff --git a/src/main/java/org/wiremock/integrations/testcontainers/WireMockContainer.java b/src/main/java/org/wiremock/integrations/testcontainers/WireMockContainer.java index e3f9104..5c96d65 100644 --- a/src/main/java/org/wiremock/integrations/testcontainers/WireMockContainer.java +++ b/src/main/java/org/wiremock/integrations/testcontainers/WireMockContainer.java @@ -20,6 +20,8 @@ import org.testcontainers.containers.wait.strategy.WaitStrategy; import org.testcontainers.images.builder.Transferable; import org.testcontainers.shaded.com.google.common.io.Resources; +import org.testcontainers.utility.ComparableVersion; +import org.testcontainers.utility.DockerImageName; import org.testcontainers.utility.MountableFile; import java.io.File; @@ -43,8 +45,13 @@ * but other images can be included too at your own risk. */ public class WireMockContainer extends GenericContainer { - private static final String DEFAULT_IMAGE_NAME = "wiremock/wiremock"; - private static final String DEFAULT_TAG = "latest"; + + public static final String OFFICIAL_IMAGE_NAME = "wiremock/wiremock"; + private static final String WIREMOCK_2_LATEST_TAG = "2.35.0"; + /*package*/ static final String WIREMOCK_2_MINIMUM_SUPPORTED_VERSION = "2.0.0"; + + public static final DockerImageName WIREMOCK_2_LATEST = + DockerImageName.parse(OFFICIAL_IMAGE_NAME).withTag(WIREMOCK_2_LATEST_TAG); private static final String MAPPINGS_DIR = "/home/wiremock/mappings/"; private static final String FILES_DIR = "/home/wiremock/__files/"; @@ -61,16 +68,28 @@ public class WireMockContainer extends GenericContainer { private final Map extensions = new HashMap<>(); private boolean isBannerDisabled = true; - public WireMockContainer() { - this(DEFAULT_TAG); + /** + * Create image from the specified full image name (repo, image, tag) + */ + public WireMockContainer(String image) { + this(DockerImageName.parse(image)); } - public WireMockContainer(String version) { - this(DEFAULT_IMAGE_NAME, version); - } + public WireMockContainer(DockerImageName dockerImage) { + super(dockerImage); + dockerImage.assertCompatibleWith(new DockerImageName(OFFICIAL_IMAGE_NAME)); + + // Verify the minimum version for the official image + final ComparableVersion version = new ComparableVersion(dockerImage.getVersionPart()); + if (!version.isSemanticVersion()) { // Accept only images when compatibility is declared explicitly + // TODO: We cannot extract compatibleSubstituteFor from Testcontainers API - https://github.com/testcontainers/testcontainers-java/issues/7305 + } else { + boolean isLessThanBaseVersion = version.isLessThan(WIREMOCK_2_MINIMUM_SUPPORTED_VERSION); + if (OFFICIAL_IMAGE_NAME.equals(dockerImage.getUnversionedPart()) && isLessThanBaseVersion) { + throw new IllegalArgumentException("For the official image, the WireMock version must be >= " + WIREMOCK_2_MINIMUM_SUPPORTED_VERSION); + } + } - public WireMockContainer(String image, String version) { - super(image + ":" + version); wireMockArgs = new StringBuilder(); setWaitStrategy(DEFAULT_WAITER); } diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerBannerTest.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerBannerTest.java index 9b14add..a2d3d2d 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("2.35.0"); + WireMockContainer wireMockContainer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST); @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 825fb8f..440269c 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("2.35.0") + WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) .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 686487a..353b019 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsCombinationTest.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsCombinationTest.java @@ -39,7 +39,7 @@ class WireMockContainerExtensionsCombinationTest { private static final Logger LOGGER = LoggerFactory.getLogger(WireMockContainerExtensionsCombinationTest.class); @Container - WireMockContainer wiremockServer = new WireMockContainer("2.35.0") + WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) .withLogConsumer(new Slf4jLogConsumer(LOGGER)) .withMapping("json-body-transformer", WireMockContainerExtensionsCombinationTest.class, "json-body-transformer.json") .withExtension("Webhook", diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest.java index 3b80727..0428f6b 100644 --- a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest.java +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerExtensionsWebhookTest.java @@ -56,7 +56,7 @@ class WireMockContainerExtensionsWebhookTest { TestHttpServer applicationServer = TestHttpServer.newInstance(); @Container - WireMockContainer wiremockServer = new WireMockContainer("2.35.0") + WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) .withLogConsumer(new Slf4jLogConsumer(LOGGER)) .withCliArg("--global-response-templating") .withMapping("webhook-callback-template", WireMockContainerExtensionsWebhookTest.class, "webhook-callback-template.json") diff --git a/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerJunit4Test.java b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerJunit4Test.java index 9672c06..8397d8b 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("2.35.0") + public WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) .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 32c5690..2ede03d 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("2.35.0") + WireMockContainer wiremockServer = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST) .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 new file mode 100644 index 0000000..f1c7cd4 --- /dev/null +++ b/src/test/java/org/wiremock/integrations/testcontainers/WireMockContainerUnitTest.java @@ -0,0 +1,76 @@ +package org.wiremock.integrations.testcontainers; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.testcontainers.utility.DockerImageName; + +import static org.assertj.core.api.Assertions.assertThat; + +public class WireMockContainerUnitTest { + + @Test + public void shouldInitWithDefault() { + WireMockContainer container = new WireMockContainer(WireMockContainer.WIREMOCK_2_LATEST); + } + + @Test + public void shouldInitWithHigherCompatibleVersion() { + WireMockContainer container = new WireMockContainer( + new DockerImageName(WireMockContainer.OFFICIAL_IMAGE_NAME, "2.100.0") + ); + } + + @Test + public void shouldFailForOlderImage() { + IllegalArgumentException ex = Assertions.assertThrows(IllegalArgumentException.class, () -> { + WireMockContainer container = new WireMockContainer( + new DockerImageName(WireMockContainer.OFFICIAL_IMAGE_NAME, "1.239.0")); + }); + assertThat(ex.getMessage()) + .as("Wrong exception message") + .contains("For the official image, the WireMock version must be >= " + WireMockContainer.WIREMOCK_2_MINIMUM_SUPPORTED_VERSION); + } + + @Test + public void shouldInitWithVersionedTestImagesWithSubstitution() { + // TODO: Should it be accepted by default + WireMockContainer container = new WireMockContainer( + new DockerImageName(WireMockContainer.WIREMOCK_2_LATEST.getUnversionedPart(), + WireMockContainer.WIREMOCK_2_LATEST.getVersionPart()+ "-test") + .asCompatibleSubstituteFor(WireMockContainer.WIREMOCK_2_LATEST)); + } + + @Test + public void shouldInitWithVersionSubstitution() { + WireMockContainer container = new WireMockContainer( + new DockerImageName(WireMockContainer.OFFICIAL_IMAGE_NAME, "test") + .asCompatibleSubstituteFor(WireMockContainer.WIREMOCK_2_LATEST)); + } + + @Test + @Disabled("Requires https://github.com/testcontainers/testcontainers-java/issues/7305") + public void shouldFailForUnversionedImage() { + IllegalStateException ex = Assertions.assertThrows(IllegalStateException.class, () -> { + WireMockContainer container = new WireMockContainer( + new DockerImageName(WireMockContainer.OFFICIAL_IMAGE_NAME, "test")); + }); + assertThat(ex.getMessage()) + .as("Wrong exception message") + .contains("Failed to verify that image") + .contains("is a compatible substitute for '" + WireMockContainer.OFFICIAL_IMAGE_NAME + "'"); + } + + @Test + public void shouldFailCustomImageWithoutSubstitution() { + IllegalStateException ex = Assertions.assertThrows(IllegalStateException.class, () -> { + WireMockContainer container = new WireMockContainer( + new DockerImageName("mycorp/mywiremockimage", WireMockContainer.WIREMOCK_2_LATEST.getVersionPart())); + }); + assertThat(ex.getMessage()) + .as("Wrong exception message") + .contains("Failed to verify that image") + .contains("is a compatible substitute for '" + WireMockContainer.OFFICIAL_IMAGE_NAME + "'"); + } + +}