Add support for port and random port in WireMock

User can @AutoConfigureWireMock(port=0) for instance. Still missing:
declarative HTTPS.
This commit is contained in:
Dave Syer
2016-07-21 17:16:16 +01:00
parent 472cd89768
commit b47ea3b0cd
10 changed files with 251 additions and 9 deletions

View File

@@ -22,6 +22,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.test.autoconfigure.properties.PropertyMapping;
import org.springframework.context.annotation.Import;
/**
@@ -32,6 +33,9 @@ import org.springframework.context.annotation.Import;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(WireMockConfiguration.class)
@PropertyMapping("wiremock.server")
public @interface AutoConfigureWireMock {
int port() default 8080;
}

View File

@@ -40,6 +40,7 @@ import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
import org.springframework.boot.context.embedded.Ssl;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
@@ -125,11 +126,16 @@ class SpringBootHttpServer
@Override
public int port() {
return this.options.portNumber();
if (options.httpsSettings().enabled()) {
return options.portNumber();
}
EmbeddedWebApplicationContext embedded = (EmbeddedWebApplicationContext) context;
return embedded.getEmbeddedServletContainer().getPort();
}
@Override
public int httpsPort() {
// TODO HTTPS on random port
return this.options.httpsSettings().port();
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.wiremock;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.util.SocketUtils;
/**
* @author Dave Syer
*
*/
@Order(Ordered.LOWEST_PRECEDENCE)
public class WireMockApplicationListener implements ApplicationListener<ApplicationPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
registerPort(event.getApplicationContext().getEnvironment());
}
private void registerPort(ConfigurableEnvironment environment) {
if (environment.getProperty("wiremock.server.port", Integer.class, 0) == 0) {
MutablePropertySources propertySources = environment.getPropertySources();
if (!propertySources.contains("wiremock")) {
propertySources.addFirst(
new MapPropertySource("wiremock", new HashMap<String, Object>()));
}
Map<String, Object> source = ((MapPropertySource) propertySources
.get("wiremock")).getSource();
source.put("wiremock.server.port", SocketUtils.findAvailableTcpPort(10000, 15000));
}
}
}

View File

@@ -19,8 +19,12 @@ package org.springframework.cloud.contract.wiremock;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
@@ -31,7 +35,7 @@ import com.github.tomakehurst.wiremock.core.Options;
*
*/
@Configuration
class WireMockConfiguration implements SmartLifecycle {
public class WireMockConfiguration implements SmartLifecycle, ImportAware {
private volatile boolean running;
@@ -39,13 +43,31 @@ class WireMockConfiguration implements SmartLifecycle {
@Autowired(required = false)
private Options options;
@Value("${wiremock.server.port:8080}")
private int port = 8080;
@Override
public void setImportMetadata(AnnotationMetadata metadata) {
int port = AnnotationAttributes
.fromMap(metadata
.getAnnotationAttributes(AutoConfigureWireMock.class.getName()))
.getNumber("port").intValue();
if (port>0) {
this.port = port;
}
}
@PostConstruct
public void init() {
if (options == null) {
this.options = com.github.tomakehurst.wiremock.core.WireMockConfiguration
com.github.tomakehurst.wiremock.core.WireMockConfiguration factory = com.github.tomakehurst.wiremock.core.WireMockConfiguration
.wireMockConfig()
.httpServerFactory(new SpringBootHttpServerFactory());
if (port != 8080) {
factory.port(port);
}
this.options = factory;
}
server = new WireMockServer(options);
}
@@ -53,7 +75,7 @@ class WireMockConfiguration implements SmartLifecycle {
@Override
public void start() {
server.start();
WireMock.configureFor("localhost", options.portNumber());
WireMock.configureFor("localhost", server.port());
running = true;
}

View File

@@ -0,0 +1,3 @@
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.cloud.contract.wiremock.WireMockApplicationListener

View File

@@ -15,7 +15,7 @@ import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=WiremockTestsApplication.class, properties="app.baseUrl=http://localhost:8080", webEnvironment=WebEnvironment.NONE)
@SpringBootTest(classes=WiremockTestsApplication.class, properties="app.baseUrl=http://localhost:${wiremock.server.port}", webEnvironment=WebEnvironment.NONE)
@DirtiesContext
@AutoConfigureWireMock
public class AutoConfigureWireMockApplicationTests {

View File

@@ -0,0 +1,33 @@
package org.springframework.cloud.contract.wiremock;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WiremockTestsApplication.class, properties = "app.baseUrl=http://localhost:${wiremock.server.port}", webEnvironment = WebEnvironment.NONE)
@DirtiesContext
@AutoConfigureWireMock(port = 9999)
public class AutoConfigureWireMockPortApplicationTests {
@Autowired
private Service service;
@Test
public void contextLoads() throws Exception {
stubFor(get(urlEqualTo("/resource")).willReturn(aResponse()
.withHeader("Content-Type", "text/plain").withBody("Hello World!")));
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}

View File

@@ -0,0 +1,33 @@
package org.springframework.cloud.contract.wiremock;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=WiremockTestsApplication.class, properties="app.baseUrl=http://localhost:${wiremock.server.port}", webEnvironment=WebEnvironment.NONE)
@DirtiesContext
@AutoConfigureWireMock(port=0)
public class AutoConfigureWireMockRandomPortApplicationTests {
@Autowired
private Service service;
@Test
public void contextLoads() throws Exception {
stubFor(get(urlEqualTo("/resource"))
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}