From 3938c272d5dbfeeae8c88d9e3a8b907d665bf761 Mon Sep 17 00:00:00 2001 From: rfelgent Date: Tue, 24 Sep 2024 11:39:32 +0200 Subject: [PATCH 1/4] Add support for multiple property injection (#29) Fixes #28 --------- Co-authored-by: Maciej Walkowiak --- README.md | 52 +++++++++ .../wiremock/spring/ConfigureWireMock.java | 8 ++ .../spring/WireMockContextCustomizer.java | 13 ++- .../java/app/WireMockSpringExtensionTest.java | 108 ++++++++++++------ 4 files changed, 141 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index ed7a927..36d7c52 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,58 @@ WireMock extensions can be registered independently with each `@ConfigureWireMoc @ConfigureWireMock(name = "...", property = "...", extensions = { ... }) ``` +### Single vs Multiple Property Injection + +The concept of single property injection can be described as wiring _one_ `WireMockServer` instance to _one_ property. + +```java +@SpringBootTest +@EnableWireMock({ + @ConfigureWireMock(name = "foo-service", property = "app.client-apis.foo.base-path"}), + @ConfigureWireMock(name = "bar-service", property = "app.client-apis.bar.base-path"}), + @ConfigureWireMock(name = "mojo-service", property = "app.client-apis.mojo.base-path"}) +}) +class AppIT { + @InjectWireMock("foo-service") + private WireMockServer fooService; + @InjectWireMock("bar-service") + private WireMockServer barService; + @InjectWireMock("mojo-service") + private WireMockServer mojoService; + + @Test + void contextLoads() { + // your test code + } +} +``` + +The concept of multiple property injection can be described as wiring _one_ `WireMockServer` instance to _multiple_ properties. + +```java +@SpringBootTest +@EnableWireMock({ + @ConfigureWireMock(name = "services", properties = { + "app.client-apis.foo.base-path", + "app.client-apis.bar.base-path", + "app.client-apis.mojo.base-path"}) +}) +class AppIT { + + @InjectWireMock("services") + private WireMockServer services; + + @Test + void contextLoads() { + // your test code + } +} +``` + +The *single* property injection provides a high level of isolation when mocking and stubbing 3rd pary RESTful api, because every service +is associated to its own dedicated `WireMockServer` instance. +The *multiple* property injections provides a less complex test setup at the cost of isolation. + ### Customizing mappings directory By default, each `WireMockServer` is configured to load mapping files from a classpath directory `wiremock/{server-name}/mappings`. diff --git a/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/ConfigureWireMock.java b/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/ConfigureWireMock.java index 723d38b..4a22b02 100644 --- a/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/ConfigureWireMock.java +++ b/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/ConfigureWireMock.java @@ -32,10 +32,18 @@ /** * The name of Spring property to inject the {@link WireMockServer#baseUrl()} * + * @deprecated please use {@link ConfigureWireMock#properties()} * @return the name of Spring property to inject the {@link WireMockServer#baseUrl()} */ + @Deprecated(since = "2.1.3") String property() default ""; + /** + * Names of Spring properties to inject the {@link WireMockServer#baseUrl()}. + * + * @return names of Spring properties to inject the {@link WireMockServer#baseUrl()}. + */ + String[] properties() default {}; /** * The location of WireMock stub files. By default, stubs are resolved from classpath location wiremock-server-name/mappings/. * diff --git a/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/WireMockContextCustomizer.java b/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/WireMockContextCustomizer.java index 94ddcb2..e7e62be 100644 --- a/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/WireMockContextCustomizer.java +++ b/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/WireMockContextCustomizer.java @@ -7,6 +7,7 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.common.Notifier; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import java.util.stream.Collectors; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; import org.slf4j.Logger; @@ -91,11 +92,19 @@ private void resolveOrCreateWireMockServer(ConfigurableApplicationContext contex }); // configure Spring environment property + List propertyNames; if (StringUtils.isNotBlank(options.property())) { - String property = options.property() + "=" + newServer.baseUrl(); + propertyNames = List.of(options.property()); + } else { + propertyNames = Arrays.stream(options.properties()) + .filter(StringUtils::isNotBlank) + .collect(Collectors.toList()); + } + propertyNames.forEach(propertyName -> { + String property = propertyName + "=" + newServer.baseUrl(); LOGGER.debug("Adding property '{}' to Spring application context", property); TestPropertyValues.of(property).applyTo(context.getEnvironment()); - } + }); } else { LOGGER.info("WireMockServer with name '{}' is already configured", options.name()); } diff --git a/wiremock-spring-boot/src/test/java/app/WireMockSpringExtensionTest.java b/wiremock-spring-boot/src/test/java/app/WireMockSpringExtensionTest.java index 8a11925..0a13647 100644 --- a/wiremock-spring-boot/src/test/java/app/WireMockSpringExtensionTest.java +++ b/wiremock-spring-boot/src/test/java/app/WireMockSpringExtensionTest.java @@ -4,6 +4,7 @@ import com.maciejwalkowiak.wiremock.spring.ConfigureWireMock; import com.maciejwalkowiak.wiremock.spring.EnableWireMock; import com.maciejwalkowiak.wiremock.spring.InjectWireMock; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -13,54 +14,85 @@ import static org.assertj.core.api.Assertions.assertThat; -@SpringBootTest(classes = WireMockSpringExtensionTest.AppConfiguration.class) -@EnableWireMock({ - @ConfigureWireMock(name = "user-service", property = "user-service.url"), - @ConfigureWireMock(name = "todo-service", property = "todo-service.url"), - @ConfigureWireMock(name = "noproperty-service") -}) public class WireMockSpringExtensionTest { - @SpringBootApplication - static class AppConfiguration { + @SpringBootTest(classes = WireMockSpringExtensionTest.AppConfiguration.class) + @EnableWireMock({ + @ConfigureWireMock(name = "user-service", property = "user-service.url"), + @ConfigureWireMock(name = "todo-service", property = "todo-service.url"), + @ConfigureWireMock(name = "noproperty-service") + }) + @Nested + class SinglePropertyBindingTest { - } + @InjectWireMock("todo-service") + private WireMockServer todoWireMockServer; - @InjectWireMock("todo-service") - private WireMockServer todoWireMockServer; + @Autowired + private Environment environment; - @Autowired - private Environment environment; + @Test + void createsWiremockWithClassLevelConfigureWiremock(@InjectWireMock("user-service") WireMockServer wireMockServer) { + assertWireMockServer(wireMockServer, "user-service.url"); + } - @Test - void createsWiremockWithClassLevelConfigureWiremock(@InjectWireMock("user-service") WireMockServer wireMockServer) { - assertWireMockServer(wireMockServer, "user-service.url"); - } + @Test + void createsWiremockWithFieldLevelConfigureWiremock() { + assertWireMockServer(todoWireMockServer, "todo-service.url"); + } + + @Test + void doesNotSetPropertyWhenNotProvided(@InjectWireMock("noproperty-service") WireMockServer wireMockServer) { + assertThat(wireMockServer) + .as("inject wiremock sets null when not configured") + .isNotNull(); + } - @Test - void createsWiremockWithFieldLevelConfigureWiremock() { - assertWireMockServer(todoWireMockServer, "todo-service.url"); + private void assertWireMockServer(WireMockServer wireMockServer, String property) { + assertThat(wireMockServer) + .as("creates WireMock instance") + .isNotNull(); + assertThat(wireMockServer.baseUrl()) + .as("WireMock baseUrl is set") + .isNotNull(); + assertThat(wireMockServer.port()) + .as("sets random port") + .isNotZero(); + assertThat(environment.getProperty(property)) + .as("sets Spring property") + .isEqualTo(wireMockServer.baseUrl()); + } } - @Test - void doesNotSetPropertyWhenNotProvided(@InjectWireMock("noproperty-service") WireMockServer wireMockServer) { - assertThat(wireMockServer) - .as("creates WireMock instance") - .isNotNull(); + @SpringBootTest(classes = WireMockSpringExtensionTest.AppConfiguration.class) + @EnableWireMock({ + @ConfigureWireMock(name = "user-service", properties = {"user-service.url", "todo-service.url"}), + @ConfigureWireMock(name = "mojo-service", property = "mojo-service.url", properties = {"other-service.url"}) + }) + @Nested + class MultiplePropertiesBindingTest { + + @InjectWireMock("user-service") + private WireMockServer userServiceWireMockServer; + + @InjectWireMock("mojo-service") + private WireMockServer mojoServiceWireMockServer; + + @Autowired + private Environment environment; + + @Test + void bindsUrlToMultipleProperties() { + assertThat(environment.getProperty("user-service.url")).isEqualTo(userServiceWireMockServer.baseUrl()); + assertThat(environment.getProperty("todo-service.url")).isEqualTo(userServiceWireMockServer.baseUrl()); + // single property binding takes precedence over multiple properties binding + assertThat(environment.getProperty("mojo-service.url")).isEqualTo(mojoServiceWireMockServer.baseUrl()); + assertThat(environment.getProperty("other-service.url")).isNull(); + } } - private void assertWireMockServer(WireMockServer wireMockServer, String property) { - assertThat(wireMockServer) - .as("creates WireMock instance") - .isNotNull(); - assertThat(wireMockServer.baseUrl()) - .as("WireMock baseUrl is set") - .isNotNull(); - assertThat(wireMockServer.port()) - .as("sets random port") - .isNotZero(); - assertThat(environment.getProperty(property)) - .as("sets Spring property") - .isEqualTo(wireMockServer.baseUrl()); + @SpringBootApplication + static class AppConfiguration { + } } From dedbf852c3dadbcebd5567f83b8ace084a64a3d8 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Sep 2024 12:19:04 +0200 Subject: [PATCH 2/4] Set version to 2.1.3 (#43) --- example/pom.xml | 2 +- pom.xml | 2 +- wiremock-spring-boot/pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/pom.xml b/example/pom.xml index 4a280cd..82fbf05 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -7,7 +7,7 @@ com.maciejwalkowiak.spring wiremock-spring-boot-parent - 2.1.3-SNAPSHOT + 2.1.3 com.maciejwalkowiak.wiremock diff --git a/pom.xml b/pom.xml index 697a3c4..023ae33 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.maciejwalkowiak.spring wiremock-spring-boot-parent - 2.1.3-SNAPSHOT + 2.1.3 pom diff --git a/wiremock-spring-boot/pom.xml b/wiremock-spring-boot/pom.xml index ceaa468..8d5fedd 100644 --- a/wiremock-spring-boot/pom.xml +++ b/wiremock-spring-boot/pom.xml @@ -6,12 +6,12 @@ com.maciejwalkowiak.spring wiremock-spring-boot-parent - 2.1.3-SNAPSHOT + 2.1.3 ../pom.xml wiremock-spring-boot - 2.1.3-SNAPSHOT + 2.1.3 WireMock Spring Boot WireMock integration for Spring Boot From ef400e6ed55c7d33f5dc6e962a97bde6654654e5 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Sep 2024 12:35:56 +0200 Subject: [PATCH 3/4] Update readme. --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 36d7c52..07c764e 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Add the dependency to `wiremock-spring-boot`: com.maciejwalkowiak.spring wiremock-spring-boot - 2.1.2 + 2.1.3 test ``` @@ -29,7 +29,7 @@ Use `@EnableWireMock` with `@ConfigureWireMock` with tests annotated that use `S ```java @SpringBootTest @EnableWireMock({ - @ConfigureWireMock(name = "user-service", property = "user-client.url") + @ConfigureWireMock(name = "user-service", properties = "user-client.url") }) class TodoControllerTests { @@ -57,7 +57,7 @@ Note that `WireMockServer` instances are not added as beans to Spring applicatio WireMock extensions can be registered independently with each `@ConfigureWireMock`: ```java -@ConfigureWireMock(name = "...", property = "...", extensions = { ... }) +@ConfigureWireMock(name = "...", properties = "...", extensions = { ... }) ``` ### Single vs Multiple Property Injection @@ -67,9 +67,9 @@ The concept of single property injection can be described as wiring _one_ `WireM ```java @SpringBootTest @EnableWireMock({ - @ConfigureWireMock(name = "foo-service", property = "app.client-apis.foo.base-path"}), - @ConfigureWireMock(name = "bar-service", property = "app.client-apis.bar.base-path"}), - @ConfigureWireMock(name = "mojo-service", property = "app.client-apis.mojo.base-path"}) + @ConfigureWireMock(name = "foo-service", properties = "app.client-apis.foo.base-path"}), + @ConfigureWireMock(name = "bar-service", properties = "app.client-apis.bar.base-path"}), + @ConfigureWireMock(name = "mojo-service", properties = "app.client-apis.mojo.base-path"}) }) class AppIT { @InjectWireMock("foo-service") @@ -119,7 +119,7 @@ By default, each `WireMockServer` is configured to load mapping files from a cla It can be changed with setting `stubLocation` on `@ConfigureWireMock`: ```java -@ConfigureWireMock(name = "...", property = "...", stubLocation = "my-stubs") +@ConfigureWireMock(name = "...", properties = "...", stubLocation = "my-stubs") ``` Sounds good? Consider [❤️ Sponsoring](https://github.com/sponsors/maciejwalkowiak) the project! Thank you! From 0a9cfef40168e990ef2567917627b2c0a1270469 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Tue, 24 Sep 2024 12:36:19 +0200 Subject: [PATCH 4/4] back to snapshots --- example/pom.xml | 2 +- pom.xml | 2 +- wiremock-spring-boot/pom.xml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/pom.xml b/example/pom.xml index 82fbf05..4c265f2 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -7,7 +7,7 @@ com.maciejwalkowiak.spring wiremock-spring-boot-parent - 2.1.3 + 2.1.4-SNAPSHOT com.maciejwalkowiak.wiremock diff --git a/pom.xml b/pom.xml index 023ae33..c80f16a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.maciejwalkowiak.spring wiremock-spring-boot-parent - 2.1.3 + 2.1.4-SNAPSHOT pom diff --git a/wiremock-spring-boot/pom.xml b/wiremock-spring-boot/pom.xml index 8d5fedd..2486d18 100644 --- a/wiremock-spring-boot/pom.xml +++ b/wiremock-spring-boot/pom.xml @@ -6,12 +6,12 @@ com.maciejwalkowiak.spring wiremock-spring-boot-parent - 2.1.3 + 2.1.4-SNAPSHOT ../pom.xml wiremock-spring-boot - 2.1.3 + 2.1.4-SNAPSHOT WireMock Spring Boot WireMock integration for Spring Boot