From 8987c8a9a49d24772ae2a018df308ec3731d92c8 Mon Sep 17 00:00:00 2001 From: wolfchkov Date: Thu, 31 Aug 2023 14:14:28 +0300 Subject: [PATCH] adding testcontainer for wiremock (#1449) Co-authored-by: Volchkov Andrey --- README.adoc | 2 + embedded-wiremock/README.adoc | 73 +++++++++++++++++++ embedded-wiremock/pom.xml | 50 +++++++++++++ ...mbeddedWiremockBootstrapConfiguration.java | 69 ++++++++++++++++++ .../wiremock/WiremockProperties.java | 23 ++++++ ...itional-spring-configuration-metadata.json | 25 +++++++ .../main/resources/META-INF/spring.factories | 2 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../wiremock/DisableWiremockTest.java | 37 ++++++++++ ...dedWiremockBootstrapConfigurationTest.java | 72 ++++++++++++++++++ pom.xml | 1 + testcontainers-spring-boot-bom/pom.xml | 5 ++ 12 files changed, 360 insertions(+) create mode 100644 embedded-wiremock/README.adoc create mode 100644 embedded-wiremock/pom.xml create mode 100644 embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.java create mode 100644 embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/WiremockProperties.java create mode 100644 embedded-wiremock/src/main/resources/META-INF/additional-spring-configuration-metadata.json create mode 100644 embedded-wiremock/src/main/resources/META-INF/spring.factories create mode 100644 embedded-wiremock/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/DisableWiremockTest.java create mode 100644 embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfigurationTest.java diff --git a/README.adoc b/README.adoc index 58bfe7bc3..0b1be92b7 100644 --- a/README.adoc +++ b/README.adoc @@ -333,6 +333,8 @@ embedded: === link:embedded-cockroachdb/README.adoc[embedded-cockroachdb] === link:embedded-git/README.adoc[embedded-git] +=== link:embedded-wiremock/README.adoc[embedded-wiremock] + == How to contribute diff --git a/embedded-wiremock/README.adoc b/embedded-wiremock/README.adoc new file mode 100644 index 000000000..1b749d1d5 --- /dev/null +++ b/embedded-wiremock/README.adoc @@ -0,0 +1,73 @@ +=== embedded-wiremock + +==== Maven dependency + +.pom.xml +[source,xml] +---- + + com.playtika.testcontainers + embedded-wiremock + test + +---- + +==== Consumes (via `bootstrap.properties`) + +* `embedded.wiremock.enabled` `(true|false, default is true)` +* `embedded.wiremock.reuseContainer` `(true|false, default is false)` +* `embedded.wiremock.dockerImage` `(default is 'wiremock/wiremock:2.32.0')` +* `embedded.wiremock.host` `(default is 'localhost')` +* `embedded.wiremock.port` `(int, default is 8990)` + + +==== Produces + +* `embedded.wiremock.host` +* `embedded.wiremock.port` (mapped HTTP port) +* `embedded.wiremock.networkAlias` +* `embedded.wiremock.internalPort` +* Bean `GenericContainer embeddedWiremock` + + +==== Example + +Add wiremock dependency with test scope (to use wiremock client to configure stubs, etc.): + +.pom.xml +[source,xml] +---- + + com.github.tomakehurst + wiremock + test + +---- + +Set up and use the wiremock: + +[source,java] +---- +class SomeTest { + //... + @Value("${embedded.wiremock.host}") + String wiremockHost; + + @Value("${embedded.wiremock.port}") + int wiremockPort; + + @BeforeEach + void setUp() { + WireMock.configureFor(wiremockHost, wiremockPort); + } + + @Test + void doTest() { + // configure stub + stubFor(get("/say-hello") + .willReturn(ok("Hello world!"))); + // test something + } + //... + } +---- diff --git a/embedded-wiremock/pom.xml b/embedded-wiremock/pom.xml new file mode 100644 index 000000000..002e2c417 --- /dev/null +++ b/embedded-wiremock/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + testcontainers-spring-boot-parent + com.playtika.testcontainers + 3.0.0-RC9 + ../testcontainers-spring-boot-parent + + + embedded-wiremock + + + 2.27.2 + + + + + com.playtika.testcontainers + testcontainers-common + + + + com.github.tomakehurst + wiremock + ${wiremock.version} + test + + + commons-logging + commons-logging + + + + + + io.rest-assured + rest-assured + test + + + commons-logging + commons-logging + + + + + \ No newline at end of file diff --git a/embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.java b/embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.java new file mode 100644 index 000000000..ce24ea3e0 --- /dev/null +++ b/embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.java @@ -0,0 +1,69 @@ +package com.playtika.testcontainers.wiremock; + +import com.playtika.testcontainer.common.spring.DockerPresenceBootstrapConfiguration; +import com.playtika.testcontainer.common.utils.ContainerUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.containers.wait.strategy.WaitStrategy; + +import java.util.LinkedHashMap; + +import static com.playtika.testcontainer.common.utils.ContainerUtils.configureCommonsAndStart; +import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; + +@Slf4j +@Order(HIGHEST_PRECEDENCE) +@Configuration +@ConditionalOnExpression("${embedded.containers.enabled:true}") +@AutoConfigureAfter(DockerPresenceBootstrapConfiguration.class) +@ConditionalOnProperty(name = "embedded.wiremock.enabled", havingValue = "true", matchIfMissing = true) +@EnableConfigurationProperties(WiremockProperties.class) +public class EmbeddedWiremockBootstrapConfiguration { + + static final String BEAN_NAME_EMBEDDED_WIREMOCK = "embeddedWiremock"; + private static final String WIREMOCK_NETWORK_ALIAS = "wiremock.testcontainer.docker"; + private static final WaitStrategy DEFAULT_WAITER = Wait.forHttp("/__admin/mappings") + .withMethod("GET") + .forStatusCode(200); + + @Bean(value = BEAN_NAME_EMBEDDED_WIREMOCK, destroyMethod = "stop") + public GenericContainer wiremockContainer(ConfigurableEnvironment environment, + WiremockProperties properties) { + GenericContainer wiremock = + new GenericContainer<>(ContainerUtils.getDockerImageName(properties)) + .waitingFor(DEFAULT_WAITER) + .withCommand("--port " + properties.getPort()) + .withExposedPorts(properties.getPort()) + .withNetworkAliases(WIREMOCK_NETWORK_ALIAS); + + wiremock = configureCommonsAndStart(wiremock, properties, log); + registerWiremockEnvironment(wiremock, environment, properties); + return wiremock; + } + + private void registerWiremockEnvironment(GenericContainer container, ConfigurableEnvironment environment, WiremockProperties properties) { + Integer mappedPort = container.getMappedPort(properties.getPort()); + String host = container.getHost(); + + LinkedHashMap map = new LinkedHashMap<>(); + map.put("embedded.wiremock.port", mappedPort); + map.put("embedded.wiremock.host", host); + map.put("embedded.wiremock.networkAlias", WIREMOCK_NETWORK_ALIAS); + map.put("embedded.wiremock.internalPort", properties.getPort()); + + log.info("Started wiremock. Connection Details: {}", map); + + MapPropertySource propertySource = new MapPropertySource("embeddedWiremockInfo", map); + environment.getPropertySources().addFirst(propertySource); + } +} diff --git a/embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/WiremockProperties.java b/embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/WiremockProperties.java new file mode 100644 index 000000000..6d8369f10 --- /dev/null +++ b/embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/WiremockProperties.java @@ -0,0 +1,23 @@ +package com.playtika.testcontainers.wiremock; + +import com.playtika.testcontainer.common.properties.CommonContainerProperties; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Data +@EqualsAndHashCode(callSuper = true) +@ConfigurationProperties("embedded.wiremock") +public class WiremockProperties extends CommonContainerProperties { + + private String host = "localhost"; + private int port = 8990; + + // https://hub.docker.com/r/wiremock/wiremock + @Override + public String getDefaultDockerImage() { + // Please don`t remove this comment. + // renovate: datasource=docker + return "wiremock/wiremock:2.32.0"; + } +} diff --git a/embedded-wiremock/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/embedded-wiremock/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 000000000..15f061271 --- /dev/null +++ b/embedded-wiremock/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,25 @@ +{ + "properties": [ + { + "name": "embedded.wiremock.enabled", + "type": "java.lang.String", + "defaultValue": "true" + }, + { + "name": "embedded.wiremock.dockerImage", + "type": "java.lang.String", + "defaultValue": "wiremock/wiremock:2.32.0" + }, + { + "name": "embedded.wiremock.host", + "type": "java.lang.String", + "defaultValue": "localhost" + }, + { + "name": "embedded.wiremock.port", + "type": "java.lang.Integer", + "description": "The container internal port. Will be overwritten with mapped port.", + "defaultValue": "8990" + } + ] +} diff --git a/embedded-wiremock/src/main/resources/META-INF/spring.factories b/embedded-wiremock/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..e63a0a45b --- /dev/null +++ b/embedded-wiremock/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.cloud.bootstrap.BootstrapConfiguration=\ +com.playtika.testcontainers.wiremock.EmbeddedWiremockBootstrapConfiguration diff --git a/embedded-wiremock/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/embedded-wiremock/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000..23c33abe7 --- /dev/null +++ b/embedded-wiremock/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.playtika.testcontainers.wiremock.EmbeddedWiremockBootstrapConfiguration diff --git a/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/DisableWiremockTest.java b/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/DisableWiremockTest.java new file mode 100644 index 000000000..e0701bd1d --- /dev/null +++ b/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/DisableWiremockTest.java @@ -0,0 +1,37 @@ +package com.playtika.testcontainers.wiremock; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.testcontainers.containers.Container; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DisableWiremockTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(EmbeddedWiremockBootstrapConfiguration.class)); + + @Test + public void shouldSkipEmbeddedWiremockBootstrapConfiguration() { + contextRunner + .withPropertyValues( + "embedded.wiremock.enabled=false" + ) + .run((context) -> assertThat(context) + .hasNotFailed() + .doesNotHaveBean(Container.class)); + } + + @Test + public void shouldSkipEmbeddedWiremockBootstrapConfigurationWhenContainersDisabled() { + contextRunner + .withPropertyValues( + "embedded.containers.enabled=false" + ) + .run((context) -> assertThat(context) + .hasNotFailed() + .doesNotHaveBean(Container.class)); + } + +} diff --git a/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfigurationTest.java b/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfigurationTest.java new file mode 100644 index 000000000..6ad192ba4 --- /dev/null +++ b/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfigurationTest.java @@ -0,0 +1,72 @@ +package com.playtika.testcontainers.wiremock; + +import com.github.tomakehurst.wiremock.client.WireMock; +import io.restassured.RestAssured; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.ConfigurableEnvironment; + +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.equalTo; + +@Slf4j +@SpringBootTest( + classes = EmbeddedWiremockBootstrapConfigurationTest.TestConfiguration.class, + properties = { + "embedded.wiremock.enabled=true" + } +) +public class EmbeddedWiremockBootstrapConfigurationTest { + + @Autowired + ConfigurableEnvironment environment; + + @Value("${embedded.wiremock.host}") + String wiremockHost; + + @Value("${embedded.wiremock.port}") + int wiremockPort; + + @BeforeEach + void setUp() { + WireMock.configureFor(wiremockHost, wiremockPort); + RestAssured.port = wiremockPort; + } + + @Test + void shouldRequestWiremockStub() { + stubFor(get("/say-hello") + .willReturn(ok("Hello world!"))); + + given() + .get("/say-hello") + .then() + .assertThat() + .log().all() + .statusCode(200) + .body(equalTo("Hello world!")); + } + + @Test + public void propertiesAreAvailable() { + assertThat(environment.getProperty("embedded.wiremock.port")).isNotEmpty(); + assertThat(environment.getProperty("embedded.wiremock.host")).isNotEmpty(); + assertThat(environment.getProperty("embedded.wiremock.networkAlias")).isNotEmpty(); + assertThat(environment.getProperty("embedded.wiremock.internalPort")).isNotEmpty(); + } + + @EnableAutoConfiguration + @Configuration + static class TestConfiguration { + } +} diff --git a/pom.xml b/pom.xml index 3e00c1eda..d67364494 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,7 @@ embedded-git embedded-zookeeper embedded-couchbase + embedded-wiremock diff --git a/testcontainers-spring-boot-bom/pom.xml b/testcontainers-spring-boot-bom/pom.xml index 6e069425f..ee493ce7f 100644 --- a/testcontainers-spring-boot-bom/pom.xml +++ b/testcontainers-spring-boot-bom/pom.xml @@ -220,6 +220,11 @@ embedded-git ${project.version} + + com.playtika.testcontainers + embedded-wiremock + ${project.version} +