Skip to content

Commit

Permalink
Merge pull request #56 from wiremock/feature/configure-wiremock-for-c…
Browse files Browse the repository at this point in the history
…orrect

fix: wiremock default port was not always configured
  • Loading branch information
tomasbjerre authored Oct 11, 2024
2 parents 99c2fde + 14b3f3f commit 35f7867
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 20 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ allprojects {
testImplementation platform('org.junit:junit-bom:5.11.2')
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.junit.platform:junit-platform-launcher'
testImplementation 'io.rest-assured:rest-assured:5.5.0'

constraints {
implementation('org.apache.commons:commons-compress:1.26.0') {
Expand Down Expand Up @@ -58,6 +59,5 @@ project('wiremock-spring-boot-example', {
implementation "org.springframework.boot:spring-boot-starter-webflux:3.3.4"

testImplementation rootProject
testImplementation 'io.rest-assured:rest-assured:5.5.0'
}
})
2 changes: 1 addition & 1 deletion src/main/java/org/wiremock/spring/EnableWireMock.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(org.wiremock.spring.internal.WireMockSpringExtension.class)
@ExtendWith(org.wiremock.spring.internal.WireMockSpringJunitExtension.class)
public @interface EnableWireMock {
/**
* A list of {@link com.github.tomakehurst.wiremock.WireMockServer} configurations. For each
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.wiremock.spring.internal;

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -45,11 +44,7 @@ public WireMockContextCustomizer(final ConfigureWireMock... configurations) {
public void customizeContext(
final ConfigurableApplicationContext context, final MergedContextConfiguration mergedConfig) {
for (final ConfigureWireMock configureWiremock : this.configuration) {
final WireMockServer wireMockServer =
this.resolveOrCreateWireMockServer(context, configureWiremock);
if (this.configuration.size() == 1) {
WireMock.configureFor(wireMockServer.port());
}
this.resolveOrCreateWireMockServer(context, configureWiremock);
}
}

Expand All @@ -67,6 +62,11 @@ private WireMockServer resolveOrCreateWireMockServer(
return wireMockServer;
}

/**
* The docs in {@link ContextCustomizer} states that equals and hashcode is being used for caching
* and needs implementation. The customizeContext method will not be invoked for all tests,
* because of caching.
*/
@Override
public boolean equals(final Object o) {
if (this == o) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@
* @author Maciej Walkowiak
*/
public class WireMockContextCustomizerFactory implements ContextCustomizerFactory {
private static final ConfigureWireMock DEFAULT_CONFIGURE_WIREMOCK =
static final ConfigureWireMock DEFAULT_CONFIGURE_WIREMOCK =
DefaultConfigureWireMock.class.getAnnotation(ConfigureWireMock.class);

@ConfigureWireMock(name = "wiremock")
private static class DefaultConfigureWireMock {}

static ConfigureWireMock[] getConfigureWireMocksOrDefault(final ConfigureWireMock... value) {
if (value == null || value.length == 0) {
return new ConfigureWireMock[] {WireMockContextCustomizerFactory.DEFAULT_CONFIGURE_WIREMOCK};
}
return value;
}

@Override
public ContextCustomizer createContextCustomizer(
final Class<?> testClass, final List<ContextConfigurationAttributes> configAttributes) {
Expand Down Expand Up @@ -54,12 +61,7 @@ void add(final ConfigureWireMock... annotations) {
void parse(final Class<?> clazz) {
final EnableWireMock annotation = AnnotationUtils.findAnnotation(clazz, EnableWireMock.class);
if (annotation != null) {
final ConfigureWireMock[] value = annotation.value();
if (value.length == 0) {
this.add(WireMockContextCustomizerFactory.DEFAULT_CONFIGURE_WIREMOCK);
} else {
this.add(value);
}
this.add(getConfigureWireMocksOrDefault(annotation.value()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.platform.commons.support.AnnotationSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.wiremock.spring.ConfigureWireMock;
import org.wiremock.spring.EnableWireMock;
import org.wiremock.spring.InjectWireMock;

/**
Expand All @@ -20,8 +25,9 @@
*
* @author Maciej Walkowiak
*/
public class WireMockSpringExtension
public class WireMockSpringJunitExtension
implements BeforeEachCallback, AfterEachCallback, ParameterResolver {
private static final Logger LOGGER = LoggerFactory.getLogger(WireMockSpringJunitExtension.class);

@Override
public void beforeEach(final ExtensionContext extensionContext) throws Exception {
Expand All @@ -30,6 +36,45 @@ public void beforeEach(final ExtensionContext extensionContext) throws Exception

// inject properties into test class fields
injectWireMockInstances(extensionContext, InjectWireMock.class, InjectWireMock::value);

this.configureWireMockForDefaultInstance(extensionContext);
}

private void configureWireMockForDefaultInstance(final ExtensionContext extensionContext) {
final List<Object> instances = extensionContext.getRequiredTestInstances().getAllInstances();
WireMockServer wiremock = null;
String wireMockName = null;
for (final Object instance : instances) {
final EnableWireMock enableWireMockAnnotation =
AnnotationUtils.findAnnotation(instance.getClass(), EnableWireMock.class);
if (enableWireMockAnnotation == null) {
continue;
}
final ConfigureWireMock[] wireMockServers =
WireMockContextCustomizerFactory.getConfigureWireMocksOrDefault(
enableWireMockAnnotation.value());
if (wireMockServers.length > 1) {
LOGGER.info(
"Not configuring WireMock for default instance when several ConfigureWireMock ("
+ wireMockServers.length
+ ")");
}
if (wiremock != null) {
LOGGER.info("Not configuring WireMock for default instance when several candidates found");
return;
}
wireMockName = wireMockServers[0].name();
wiremock = Store.INSTANCE.findRequiredWireMockInstance(extensionContext, wireMockName);
}
if (wiremock != null) {
LOGGER.info(
"Configuring WireMock for default instance, '"
+ wireMockName
+ "' on '"
+ wiremock.port()
+ "'.");
WireMock.configureFor(wiremock.port());
}
}

@Override
Expand Down
81 changes: 81 additions & 0 deletions src/test/java/app/NestedClassSingleWireMockTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package app;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static org.assertj.core.api.Assertions.assertThat;

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import io.restassured.RestAssured;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;
import org.wiremock.spring.ConfigureWireMock;
import org.wiremock.spring.EnableWireMock;
import org.wiremock.spring.InjectWireMock;

@SpringBootTest(classes = NestedClassSingleWireMockTest.AppConfiguration.class)
@EnableWireMock({
@ConfigureWireMock(
name = "todo-service",
baseUrlProperties = "todo-service.url",
portProperties = "todo-service.port")
})
public class NestedClassSingleWireMockTest {

@SpringBootApplication
static class AppConfiguration {}

@Autowired private Environment environment;

@InjectWireMock("todo-service")
private WireMockServer topLevelClassTodoService;

@Nested
@DisplayName("Test Something")
class NestedTest {

@InjectWireMock("todo-service")
private WireMockServer nestedClassTodoService;

@Test
void injectsWiremockServerToNestedClassField() {
this.assertWireMockServer(
this.nestedClassTodoService, "todo-service.url", "todo-service.port");
}

@Test
void injectsWiremockServerToTopLevelClassField() {
this.assertWireMockServer(
NestedClassSingleWireMockTest.this.topLevelClassTodoService,
"todo-service.url",
"todo-service.port");
}

private void assertWireMockServer(
final WireMockServer wireMockServer, final String property, final String portProperty) {
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(
Integer.valueOf(
NestedClassSingleWireMockTest.this.environment.getProperty(portProperty)))
.as("sets Spring port property")
.isEqualTo(wireMockServer.port());
assertThat(NestedClassSingleWireMockTest.this.environment.getProperty(property))
.as("sets Spring property")
.isEqualTo(wireMockServer.baseUrl());

// Test that WireMock is configured for the correct WireMock instance
// Suffixed with port to make it differ for different test runs and servers
final String mockedPath = "/the_default_prop_mock-" + wireMockServer.port();
WireMock.stubFor(get(mockedPath).willReturn(aResponse().withStatus(202)));
RestAssured.baseURI = wireMockServer.baseUrl();
RestAssured.when().get(mockedPath).then().statusCode(202);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static org.assertj.core.api.Assertions.assertThat;

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.wiremock.spring.EnableWireMock;
import org.wiremock.spring.InjectWireMock;

@SpringBootTest
@EnableWireMock
Expand All @@ -21,14 +24,26 @@ class DefaultPropertiesTest {
@Value("${wiremock.server.port}")
private String wiremockPort;

@InjectWireMock WireMockServer wireMockServer;

@BeforeEach
public void before() {
WireMock.stubFor(get("/the_default_prop_mock").willReturn(aResponse().withStatus(202)));
}
public void before() {}

@Test
void test() {
void testCanInvoke() {
WireMock.stubFor(get("/the_default_prop_mock").willReturn(aResponse().withStatus(202)));

RestAssured.baseURI = this.wiremockUrl;
RestAssured.when().get("/the_default_prop_mock").then().statusCode(202);
}

@Test
void testUrlNotNull() {
assertThat(this.wiremockUrl).isNotNull();
}

@Test
void testPortNotNull() {
assertThat(this.wiremockPort).isNotNull();
}
}

0 comments on commit 35f7867

Please sign in to comment.