Skip to content

Commit

Permalink
feat: HTTP and HTTPS in same mock (refs #62)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasbjerre committed Nov 2, 2024
1 parent fdb382c commit 7ce0021
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 41 deletions.
29 changes: 25 additions & 4 deletions src/main/java/org/wiremock/spring/ConfigureWireMock.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,24 @@
public @interface ConfigureWireMock {

/**
* Port on which WireMock server is going to listen. {@code 0} means WireMock will pick random
* port.
* Port on which WireMock server is going to listen.
*
* <p>{@code -1} means disabled.
*
* <p>{@code 0} means WireMock will pick random available port.
*
* <p>{@code >0} means that static port will be used.
*
* @return WireMock server port
*/
int port() default 0;

/**
* @return true for HTTPS, else false.
* Same as {@link #port()} but for HTTPS.
*
* @return HTTPS port to use.
*/
boolean useHttps() default false;
int httpsPort() default -1;

/**
* The name of WireMock server.
Expand All @@ -49,13 +56,27 @@
*/
String[] portProperties() default {"wiremock.server.port"};

/**
* Names of Spring properties to inject the {@link WireMockServer#httpsPort()}
*
* @return names of Spring properties to inject the {@link WireMockServer#httpsPort()}
*/
String[] httpsPortProperties() default {"wiremock.server.httpsPort"};

/**
* Names of Spring properties to inject the {@link WireMockServer#baseUrl()}.
*
* @return names of Spring properties to inject the {@link WireMockServer#baseUrl()}.
*/
String[] baseUrlProperties() default {"wiremock.server.baseUrl"};

/**
* Names of Spring properties to inject the {@link WireMockServer#baseUrl()}.
*
* @return names of Spring properties to inject the {@link WireMockServer#baseUrl()}.
*/
String[] httpsBaseUrlProperties() default {"wiremock.server.httpsBaseUrl"};

/**
* Classpaths to pass to {@link WireMockConfiguration#usingFilesUnderClasspath(String)}. First one
* that is found will be used. If a {@link #name()} is supplied, it will first look for {@link
Expand Down
117 changes: 90 additions & 27 deletions src/main/java/org/wiremock/spring/internal/WireMockServerCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.wiremock.spring.WireMockConfigurationCustomizer;

public class WireMockServerCreator {
private static final int PORT_DISABLED = -1;
private final Logger logger;

public WireMockServerCreator(final String name) {
Expand All @@ -31,13 +32,19 @@ public WireMockServerCreator(final String name) {

public WireMockServer createWireMockServer(
final ConfigurableApplicationContext context, final ConfigureWireMock options) {
final int serverPort = this.getServerProperty(context.getEnvironment(), options);

final WireMockConfiguration serverOptions = options();
if (options.useHttps()) {
serverOptions.httpsPort(serverPort);
} else {
serverOptions.port(serverPort);

final int serverHttpsPort = this.getServerHttpsPortProperty(context.getEnvironment(), options);
final boolean httpsEnabled = serverHttpsPort != PORT_DISABLED;
if (httpsEnabled) {
serverOptions.httpsPort(serverHttpsPort);
}

final int serverHttpPort = this.getServerHttpPortProperty(context.getEnvironment(), options);
final boolean httpEnabled = serverHttpPort != PORT_DISABLED;
if (httpEnabled) {
serverOptions.port(serverHttpPort);
}
serverOptions.notifier(new Slf4jNotifier(options.name()));

Expand Down Expand Up @@ -74,9 +81,10 @@ public WireMockServer createWireMockServer(
this.applyCustomizers(options, serverOptions);

this.logger.info(
"Configuring WireMockServer with name '{}' on port: {}",
"Configuring WireMockServer with name '{}' on HTTP port: {} and HTTPS port: {}",
options.name(),
serverOptions.portNumber());
serverOptions.portNumber(),
serverOptions.httpsSettings().port());

final WireMockServer newServer = new WireMockServer(serverOptions);
newServer.start();
Expand All @@ -96,31 +104,64 @@ public WireMockServer createWireMockServer(
}
});

Arrays.stream(options.baseUrlProperties())
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList())
.forEach(
propertyName -> {
final String property = propertyName + "=" + newServer.baseUrl();
this.logger.info("Adding property '{}' to Spring application context", property);
TestPropertyValues.of(property).applyTo(context.getEnvironment());
});
if (httpEnabled) {
Arrays.stream(options.baseUrlProperties())
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList())
.forEach(
propertyName -> {
final String property =
propertyName + "=" + String.format("http://localhost:%d", newServer.port());
this.logger.info(
"Adding property '{}' with HTTP base URL to Spring application context",
property);
TestPropertyValues.of(property).applyTo(context.getEnvironment());
});

Arrays.stream(options.portProperties())
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList())
.forEach(
propertyName -> {
final int port = options.useHttps() ? newServer.httpsPort() : newServer.port();
final String property = propertyName + "=" + port;
this.logger.info("Adding property '{}' to Spring application context", property);
TestPropertyValues.of(property).applyTo(context.getEnvironment());
});
Arrays.stream(options.portProperties())
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList())
.forEach(
propertyName -> {
final String property = propertyName + "=" + newServer.port();
this.logger.info(
"Adding property '{}' with HTTP port to Spring application context", property);
TestPropertyValues.of(property).applyTo(context.getEnvironment());
});
}

if (httpsEnabled) {
Arrays.stream(options.httpsBaseUrlProperties())
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList())
.forEach(
propertyName -> {
final String property =
propertyName
+ "="
+ String.format("https://localhost:%d", newServer.httpsPort());
this.logger.info(
"Adding property '{}' with HTTPS base URL to Spring application context",
property);
TestPropertyValues.of(property).applyTo(context.getEnvironment());
});

Arrays.stream(options.httpsPortProperties())
.filter(StringUtils::isNotBlank)
.collect(Collectors.toList())
.forEach(
propertyName -> {
final String property = propertyName + "=" + newServer.httpsPort();
this.logger.info(
"Adding property '{}' with HTTPS port to Spring application context", property);
TestPropertyValues.of(property).applyTo(context.getEnvironment());
});
}

return newServer;
}

private int getServerProperty(
private int getServerHttpPortProperty(
final ConfigurableEnvironment environment, final ConfigureWireMock options) {
if (!options.usePortFromPredefinedPropertyIfFound()) {
return options.port();
Expand All @@ -142,6 +183,28 @@ private int getServerProperty(
.orElse(options.port());
}

private int getServerHttpsPortProperty(
final ConfigurableEnvironment environment, final ConfigureWireMock options) {
if (!options.usePortFromPredefinedPropertyIfFound()) {
return options.httpsPort();
}
return Arrays.stream(options.httpsPortProperties())
.filter(StringUtils::isNotBlank)
.filter(propertyName -> environment.containsProperty(propertyName))
.map(
propertyName -> {
final int predefinedPropertyValue =
Integer.parseInt(environment.getProperty(propertyName));
this.logger.info(
"Found predefined https port in property with name '{}' on port: {}",
propertyName,
predefinedPropertyValue);
return predefinedPropertyValue;
})
.findFirst()
.orElse(options.httpsPort());
}

private WireMockConfiguration usingFilesUnderClasspath(
final WireMockConfiguration serverOptions, final String resource) {
this.logger.info("Serving WireMock mappings from classpath resource: " + resource);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package app;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.anyRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
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.ConfigureWireMock;
import org.wiremock.spring.EnableWireMock;
import org.wiremock.spring.InjectWireMock;

@SpringBootTest
@EnableWireMock({@ConfigureWireMock(httpsPort = 0)})
class HttpsAndHttpTest {

@InjectWireMock private WireMockServer wiremock;

@Value("${wiremock.server.httpsPort}")
private int wiremockHttpsPort;

@Value("${wiremock.server.port}")
private int wiremockHttpPort;

@Value("${wiremock.server.httpsBaseUrl}")
private String wiremockHttpsUrl;

@Value("${wiremock.server.baseUrl}")
private String wiremockHttpUrl;

@BeforeEach
public void before() {
RestAssured.useRelaxedHTTPSValidation();
}

@Test
void testProperties() {
assertThat(this.wiremockHttpsPort).isNotNull();
assertThat(this.wiremockHttpsUrl)
.startsWith("https://")
.contains(String.valueOf(this.wiremockHttpsPort));

assertThat(this.wiremockHttpPort).isNotNull();
assertThat(this.wiremockHttpUrl)
.startsWith("http://")
.contains(String.valueOf(this.wiremockHttpPort));
}

@Test
void testInjectedClient() {
this.wiremock.stubFor(get("/injected-client").willReturn(aResponse().withStatus(202)));

RestAssured.when().get(this.wiremockHttpsUrl + "/injected-client").then().statusCode(202);
assertThat(this.wiremock.findAll(anyRequestedFor(anyUrl()))).hasSize(1);

RestAssured.when().get(this.wiremockHttpUrl + "/injected-client").then().statusCode(202);
assertThat(this.wiremock.findAll(anyRequestedFor(anyUrl()))).hasSize(2);
}

@Test
void testDefaultClient() {
WireMock.stubFor(WireMock.get("/with-default-client").willReturn(aResponse().withStatus(202)));

RestAssured.when().get(this.wiremockHttpsUrl + "/with-default-client").then().statusCode(202);
assertThat(WireMock.findAll(anyRequestedFor(anyUrl()))).hasSize(1);

RestAssured.when().get(this.wiremockHttpUrl + "/with-default-client").then().statusCode(202);
assertThat(WireMock.findAll(anyRequestedFor(anyUrl()))).hasSize(2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
import org.wiremock.spring.InjectWireMock;

@SpringBootTest
@EnableWireMock({@ConfigureWireMock(useHttps = true)})
class HttpsTest {
@EnableWireMock({@ConfigureWireMock(port = -1, httpsPort = 0)})
class HttpsOnlyTest {

@InjectWireMock private WireMockServer wiremock;

@Value("${wiremock.server.port}")
private int wiremockPort;
@Value("${wiremock.server.httpsPort}")
private int wiremockHttpsPort;

@Value("${wiremock.server.baseUrl}")
private String wiremockUrl;
@Value("${wiremock.server.httpsBaseUrl}")
private String wiremockHttpsUrl;

@BeforeEach
public void before() {
Expand All @@ -36,15 +36,17 @@ public void before() {

@Test
void testProperties() {
assertThat(this.wiremockPort).isNotNull();
assertThat(this.wiremockUrl).startsWith("https://").contains(String.valueOf(this.wiremockPort));
assertThat(this.wiremockHttpsPort).isNotNull();
assertThat(this.wiremockHttpsUrl)
.startsWith("https://")
.contains(String.valueOf(this.wiremockHttpsPort));
}

@Test
void testInjectedClient() {
this.wiremock.stubFor(get("/injected-client").willReturn(aResponse().withStatus(202)));

RestAssured.when().get(this.wiremockUrl + "/injected-client").then().statusCode(202);
RestAssured.when().get(this.wiremockHttpsUrl + "/injected-client").then().statusCode(202);

assertThat(this.wiremock.findAll(anyRequestedFor(anyUrl()))).hasSize(1);
}
Expand All @@ -53,7 +55,7 @@ void testInjectedClient() {
void testDefaultClient() {
WireMock.stubFor(WireMock.get("/with-default-client").willReturn(aResponse().withStatus(202)));

RestAssured.when().get(this.wiremockUrl + "/with-default-client").then().statusCode(202);
RestAssured.when().get(this.wiremockHttpsUrl + "/with-default-client").then().statusCode(202);

assertThat(WireMock.findAll(anyRequestedFor(anyUrl()))).hasSize(1);
}
Expand Down

0 comments on commit 7ce0021

Please sign in to comment.