From 586091b994778bb3becd5cddc1dec550d716f61d Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Sun, 29 Oct 2023 09:01:55 +0100 Subject: [PATCH 1/3] Add option to customize configuration on `@ConfigureWireMock` annotation. --- .../wiremock/spring/ConfigureWireMock.java | 8 +++ .../WireMockConfigurationCustomizer.java | 12 ++++ .../spring/WireMockContextCustomizer.java | 20 +++++- .../WireMockConfigurationCustomizerTests.java | 62 +++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizer.java create mode 100644 wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTests.java 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 4d5c7bc..723d38b 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 @@ -4,6 +4,7 @@ import java.lang.annotation.RetentionPolicy; import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; import com.github.tomakehurst.wiremock.extension.Extension; /** @@ -50,4 +51,11 @@ * @return the extensions */ Class[] extensions() default {}; + + /** + * Customizes {@link WireMockConfiguration} used by {@link WireMockServer} instance. Customizers are ordered by their natural order in this array. Each customizer must have no-arg constructor. + * + * @return the configuration customizers classes + */ + Class[] configurationCustomizers() default {}; } diff --git a/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizer.java b/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizer.java new file mode 100644 index 0000000..6483552 --- /dev/null +++ b/wiremock-spring-boot/src/main/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizer.java @@ -0,0 +1,12 @@ +package com.maciejwalkowiak.wiremock.spring; + +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; + +/** + * Customizes {@link WireMockConfiguration} programmatically. Can be registered with {@link ConfigureWireMock#configurationCustomizers()}. + * Customizer must have public no-arg constructor. + */ +public interface WireMockConfigurationCustomizer { + + void customize(WireMockConfiguration configuration, ConfigureWireMock options); +} 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 33e480e..1fc0c60 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 @@ -6,6 +6,7 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,8 +57,6 @@ public void customizeContext(ConfigurableApplicationContext context, MergedConte } private void resolveOrCreateWireMockServer(ConfigurableApplicationContext context, ConfigureWireMock options) { - LOGGER.info("Configuring WireMockServer with name '{}' on port: {}", options.name(), options.port()); - WireMockServer wireMockServer = Store.INSTANCE.findWireMockInstance(context, options.name()); if (wireMockServer == null) { @@ -70,6 +69,10 @@ private void resolveOrCreateWireMockServer(ConfigurableApplicationContext contex serverOptions.extensions(options.extensions()); } + applyCustomizers(options, serverOptions); + + LOGGER.info("Configuring WireMockServer with name '{}' on port: {}", options.name(), serverOptions.portNumber()); + WireMockServer newServer = new WireMockServer(serverOptions); newServer.start(); @@ -95,6 +98,19 @@ private void resolveOrCreateWireMockServer(ConfigurableApplicationContext contex } } + private static void applyCustomizers(ConfigureWireMock options, WireMockConfiguration serverOptions) { + for (Class customizer : options.configurationCustomizers()) { + try { + ReflectionUtils.newInstance(customizer).customize(serverOptions, options); + } catch (Exception e) { + if (e instanceof NoSuchMethodException) { + LOGGER.error("Customizer {} must have a no-arg constructor", customizer, e); + } + throw e; + } + } + } + private String resolveStubLocation(ConfigureWireMock options) { return StringUtils.isBlank(options.stubLocation()) ? "wiremock/" + options.name() : options.stubLocation(); } diff --git a/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTests.java b/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTests.java new file mode 100644 index 0000000..80dd24e --- /dev/null +++ b/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTests.java @@ -0,0 +1,62 @@ +package com.maciejwalkowiak.wiremock.spring; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.util.TestSocketUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = WireMockConfigurationCustomizerTests.AppConfiguration.class) +@EnableWireMock({ + @ConfigureWireMock( + name = "user-service", + property = "user-service.url", + configurationCustomizers = WireMockConfigurationCustomizerTests.SampleConfigurationCustomizer.class + ), + @ConfigureWireMock( + name = "todo-service", + property = "todo-service.url", + configurationCustomizers = WireMockConfigurationCustomizerTests.SampleConfigurationCustomizer.class + ), +}) +class WireMockConfigurationCustomizerTests { + private static final int USER_SERVICE_PORT = TestSocketUtils.findAvailableTcpPort(); + private static final int TODO_SERVICE_PORT = TestSocketUtils.findAvailableTcpPort(); + + static class SampleConfigurationCustomizer implements WireMockConfigurationCustomizer { + + SampleConfigurationCustomizer(String foo) { + } + + @Override + public void customize(WireMockConfiguration configuration, ConfigureWireMock options) { + if (options.name().equals("user-service")) { + configuration.port(USER_SERVICE_PORT); + } else { + configuration.port(TODO_SERVICE_PORT); + } + } + } + + @SpringBootApplication + static class AppConfiguration { + + } + + @InjectWireMock("user-service") + private WireMockServer userService; + + @InjectWireMock("todo-service") + private WireMockServer todoService; + + @Test + void foo() { + assertThat(userService.port()).isEqualTo(USER_SERVICE_PORT); + assertThat(todoService.port()).isEqualTo(TODO_SERVICE_PORT); + } + +} From 5633f0a5793bcf1c55db89eeb0cb39959b78b620 Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Sun, 29 Oct 2023 09:07:12 +0100 Subject: [PATCH 2/3] Polish --- README.md | 27 +++++++++++++++++++ ... WireMockConfigurationCustomizerTest.java} | 11 +++----- 2 files changed, 31 insertions(+), 7 deletions(-) rename wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/{WireMockConfigurationCustomizerTests.java => WireMockConfigurationCustomizerTest.java} (86%) diff --git a/README.md b/README.md index 59dd02b..565cb3e 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,33 @@ It can be changed with setting `stubLocation` on `@ConfigureWireMock`: @ConfigureWireMock(name = "...", property = "...", stubLocation = "my-stubs") ``` +### Advanced configuration + +More advanced configuration can be applied through configuration customizers: + +```java +@ConfigureWireMock( + name = "todo-service", + property = "todo-service.url", + configurationCustomizers = SampleConfigurationCustomizer.class +) +``` + +Where `SampleConfigurationCustomizer` is a class implementing `WireMockConfigurationCustomizer`: + +```java +class SampleConfigurationCustomizer implements WireMockConfigurationCustomizer { + + @Override + public void customize(WireMockConfiguration configuration, ConfigureWireMock options) { + // apply changes to configuration + } +} +``` + +> [!IMPORTANT] +> `WireMockConfigurationCustomizer` must have a no-arg constructor. + Sounds good? Consider [❤️ Sponsoring](https://github.com/sponsors/maciejwalkowiak) the project! Thank you! ## 🙏 Credits diff --git a/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTests.java b/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTest.java similarity index 86% rename from wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTests.java rename to wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTest.java index 80dd24e..4e99bfa 100644 --- a/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTests.java +++ b/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTest.java @@ -10,28 +10,25 @@ import static org.assertj.core.api.Assertions.assertThat; -@SpringBootTest(classes = WireMockConfigurationCustomizerTests.AppConfiguration.class) +@SpringBootTest(classes = WireMockConfigurationCustomizerTest.AppConfiguration.class) @EnableWireMock({ @ConfigureWireMock( name = "user-service", property = "user-service.url", - configurationCustomizers = WireMockConfigurationCustomizerTests.SampleConfigurationCustomizer.class + configurationCustomizers = WireMockConfigurationCustomizerTest.SampleConfigurationCustomizer.class ), @ConfigureWireMock( name = "todo-service", property = "todo-service.url", - configurationCustomizers = WireMockConfigurationCustomizerTests.SampleConfigurationCustomizer.class + configurationCustomizers = WireMockConfigurationCustomizerTest.SampleConfigurationCustomizer.class ), }) -class WireMockConfigurationCustomizerTests { +class WireMockConfigurationCustomizerTest { private static final int USER_SERVICE_PORT = TestSocketUtils.findAvailableTcpPort(); private static final int TODO_SERVICE_PORT = TestSocketUtils.findAvailableTcpPort(); static class SampleConfigurationCustomizer implements WireMockConfigurationCustomizer { - SampleConfigurationCustomizer(String foo) { - } - @Override public void customize(WireMockConfiguration configuration, ConfigureWireMock options) { if (options.name().equals("user-service")) { From 558ad5f3a210203ba8e9ea6ff1186dbfeb7a9c3e Mon Sep 17 00:00:00 2001 From: Maciej Walkowiak Date: Sun, 29 Oct 2023 09:08:06 +0100 Subject: [PATCH 3/3] Polish --- .../wiremock/spring/WireMockConfigurationCustomizerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTest.java b/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTest.java index 4e99bfa..0e1808a 100644 --- a/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTest.java +++ b/wiremock-spring-boot/src/test/java/com/maciejwalkowiak/wiremock/spring/WireMockConfigurationCustomizerTest.java @@ -51,7 +51,7 @@ static class AppConfiguration { private WireMockServer todoService; @Test - void foo() { + void appliesConfigurationCustomizer() { assertThat(userService.port()).isEqualTo(USER_SERVICE_PORT); assertThat(todoService.port()).isEqualTo(TODO_SERVICE_PORT); }