Fixed issues with bound ports

This commit is contained in:
Marcin Grzejszczak
2018-12-18 13:20:39 +01:00
parent d23e0c61bf
commit 7b2cce7513
17 changed files with 190 additions and 284 deletions

View File

@@ -77,7 +77,7 @@ public class WireMockConfiguration implements SmartLifecycle {
private DefaultListableBeanFactory beanFactory;
@Autowired
private WireMockProperties wireMock;
WireMockProperties wireMock;
@Autowired
private ResourceLoader resourceLoader;
@@ -100,6 +100,11 @@ public class WireMockConfiguration implements SmartLifecycle {
}
}
if (this.server == null) {
if (log.isDebugEnabled()) {
log.debug("Creating a new server at "
+ "http port [" + this.wireMock.getServer().getPort() + "] and "
+ "https port [" + this.wireMock.getServer().getHttpsPort() + "]");
}
this.server = new WireMockServer(this.options);
}
registerStubs();
@@ -126,21 +131,23 @@ public class WireMockConfiguration implements SmartLifecycle {
}
for (Resource resource : resolver.getResources(pattern)) {
this.server.addStubMapping(WireMockStubMapping
.buildFrom(StreamUtils.copyToString(resource.getInputStream(), Charset.forName("UTF-8"))));
.buildFrom(StreamUtils.copyToString(resource.getInputStream(),
Charset.forName("UTF-8"))));
}
}
}
}
int port() {
return this.server.port();
}
void reset() {
if (log.isDebugEnabled()) {
log.debug("Resetting stubs");
}
this.server.resetAll();
}
private void registerFiles(com.github.tomakehurst.wiremock.core.WireMockConfiguration factory) throws IOException {
private void registerFiles(
com.github.tomakehurst.wiremock.core.WireMockConfiguration factory)
throws IOException {
List<Resource> resources = new ArrayList<>();
for (String files : this.wireMock.getServer().getFiles()) {
if (StringUtils.hasText(files)) {
@@ -154,31 +161,46 @@ public class WireMockConfiguration implements SmartLifecycle {
}
}
if (!resources.isEmpty()) {
ResourcesFileSource fileSource = new ResourcesFileSource(resources.toArray(new Resource[0]));
ResourcesFileSource fileSource = new ResourcesFileSource(
resources.toArray(new Resource[0]));
factory.fileSource(fileSource);
}
}
@Override
public void start() {
if (isRunning()) {
if (log.isDebugEnabled()) {
log.debug("Server is already running");
}
return;
}
this.server.start();
WireMock.configureFor("localhost", this.server.port());
updateCurrentServer();
}
private void updateCurrentServer() {
WireMock.configureFor(new WireMock(this.server));
this.running = true;
if (log.isDebugEnabled()) {
log.debug("Started WireMock at port [" + this.server.port() + "]. It has [" + this.server.getStubMappings().size() + "] mappings registered");
log.debug("Started WireMock at port [" + this.server.port() + "]. It has ["
+ this.server.getStubMappings().size() + "] mappings registered");
}
WireMockUtils.getMappingsEndpoint(this.port());
}
@Override
public void stop() {
if (this.running) {
reset();
this.server.shutdownServer();
this.server.stop();
this.server = null;
this.running = false;
this.options = null;
if (log.isDebugEnabled()) {
log.debug("Stopped WireMock instance");
}
this.beanFactory.destroySingleton(WIREMOCK_SERVER_BEAN_NAME);
} else if (log.isDebugEnabled()) {
log.debug("Server already stopped");
}
}
@@ -202,7 +224,6 @@ public class WireMockConfiguration implements SmartLifecycle {
stop();
callback.run();
}
}
@ConfigurationProperties("wiremock")
@@ -269,6 +290,7 @@ class WireMockProperties {
public void setFiles(String[] files) {
this.files = files;
}
}
}
}

View File

@@ -20,11 +20,12 @@ package org.springframework.cloud.contract.wiremock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
/**
* Stops the WireMock server after each test class and restarts it before every class
* Dirties the test context if WireMock was running on a fixed port
*
* @author Marcin Grzejszczak
* @since 1.2.6
@@ -33,59 +34,51 @@ public final class WireMockTestExecutionListener extends AbstractTestExecutionLi
private static final Log log = LogFactory.getLog(WireMockTestExecutionListener.class);
@Override public void beforeTestClass(TestContext testContext) {
try {
if (wireMockConfigMissing(testContext)) {
return;
}
WireMockConfiguration wireMockConfiguration = wireMockConfiguration(testContext);
if (log.isDebugEnabled()) {
log.debug("WireMock configuration is running [" + wireMockConfiguration.isRunning() + "]");
}
if (!wireMockConfiguration.isRunning()) {
wireMockConfiguration.init();
wireMockConfiguration.start();
WireMockUtils.getMappingsEndpoint(wireMockConfiguration.port());
}
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Exception occurred while trying to init WireMock configuration", e);
@Override
public void afterTestClass(TestContext testContext) {
if (wireMockConfigurationMissing(testContext) || annotationMissing(testContext)) {
return;
}
if (portIsFixed(testContext)) {
if (log.isWarnEnabled()) {
log.warn("You've used fixed ports for WireMock setup - "
+ "will mark context as dirty. Please use random ports, as much "
+ "as possible. Your tests will be faster and more reliable and this"
+ "warning will go away");
}
testContext.markApplicationContextDirty(DirtiesContext.HierarchyMode.EXHAUSTIVE);
}
}
private boolean wireMockConfigMissing(TestContext testContext) {
boolean missing = !testContext.getApplicationContext().containsBean(WireMockConfiguration.class.getName());
private boolean annotationMissing(TestContext testContext) {
if (testContext.getTestClass()
.getAnnotationsByType(AutoConfigureWireMock.class).length == 0) {
if (log.isDebugEnabled()) {
log.debug("No @AutoConfigureWireMock annotation found on [" + testContext
.getTestClass() + "]. Skipping");
}
return true;
}
return false;
}
private boolean wireMockConfigurationMissing(TestContext testContext) {
boolean missing = !testContext.getApplicationContext()
.containsBean(WireMockConfiguration.class.getName());
if (log.isDebugEnabled()) {
log.debug("WireMockConfig is missing [" + missing + "]");
log.debug("WireMockConfiguration is missing [" + missing + "]");
}
return missing;
}
@Override public void afterTestClass(TestContext testContext) {
try {
if (wireMockConfigMissing(testContext)) {
return;
}
stopWireMockConfiguration(testContext);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Exception occurred while trying to init WireMock configuration", e);
}
}
}
private void stopWireMockConfiguration(TestContext testContext) {
WireMockConfiguration wireMockConfiguration = wireMockConfiguration(testContext);
if (wireMockConfiguration.isRunning()) {
if (log.isDebugEnabled()) {
log.debug("WireMock is running, will stop it");
}
wireMockConfiguration.stop();
}
}
private WireMockConfiguration wireMockConfiguration(TestContext testContext) {
private WireMockConfiguration wireMockConfig(TestContext testContext) {
return testContext.getApplicationContext().getBean(WireMockConfiguration.class);
}
}
private boolean portIsFixed(TestContext testContext) {
WireMockConfiguration wireMockProperties = wireMockConfig(testContext);
int httpPort = wireMockProperties.wireMock.getServer().getPort();
int httpsPort = wireMockProperties.wireMock.getServer().getHttpsPort();
return (httpPort != 0 || httpsPort != -1) && httpsPort != 0;
}
}

View File

@@ -1,65 +0,0 @@
/*
* Copyright 2013-2018 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.io.IOException;
import org.apache.http.HttpHost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.util.Assert;
/**
* Utility class to work with WireMock.
*
* @author Marcin Grzejszczak
* @since 2.0.3
*/
public final class WireMockUtils {
private WireMockUtils() {
throw new IllegalStateException("Don't instantiate");
}
/**
* Thanks to Tom Akehurst: I looked at tcpdump while running the failing
* test. HttpUrlConnection is doing something weird - it's creating a
* connection in a previous test case, which works fine, then the usual
* fin -> fin ack etc. etc. ending handshake happens. But it seems it
* isn't discarded, but reused after that. Because the server thinks
* (rightly) that the connection is closed, it just sends a RST packet.
* Calling the admin endpoint just happened to remove the dead connection
* from the pool. This also fixes the problem (which using the Java HTTP
* client): System.setProperty("http.keepAlive", "false");
**/
public static CloseableHttpResponse getMappingsEndpoint(int port) {
CloseableHttpClient client = HttpClientBuilder.create().build();
try {
CloseableHttpResponse response = client
.execute(new HttpHost("localhost", port), new HttpGet("/__admin/mappings"));
Assert.isTrue(response.getStatusLine().getStatusCode() == 200, "Status code must be 200");
return response;
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
}

View File

@@ -1,22 +1,22 @@
package org.springframework.cloud.contract.wiremock;
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.context.junit4.SpringRunner;
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 com.github.tomakehurst.wiremock.WireMockServer;
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.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=WiremockTestsApplication.class, properties="app.baseUrl=http://localhost:${wiremock.server.port}", webEnvironment=WebEnvironment.NONE)
@SpringBootTest(classes = WiremockTestsApplication.class,
properties = "app.baseUrl=http://localhost:${wiremock.server.port}", webEnvironment = WebEnvironment.NONE)
@AutoConfigureWireMock(port = 12345)
public class AutoConfigureWireMockApplicationTests {
@@ -25,8 +25,8 @@ public class AutoConfigureWireMockApplicationTests {
@Test
public void contextLoads() throws Exception {
stubFor(get(urlEqualTo("/test"))
.willReturn(aResponse().withHeader("Content-Type", "text/plain").withBody("Hello World!")));
stubFor(get(urlEqualTo("/test")).willReturn(aResponse()
.withHeader("Content-Type", "text/plain").withBody("Hello World!")));
assertThat(this.service.go()).isEqualTo("Hello World!");
}

View File

@@ -1,17 +1,19 @@
package org.springframework.cloud.contract.wiremock;
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.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=WiremockTestsApplication.class, properties="app.baseUrl=http://localhost:${wiremock.server.port}", webEnvironment=WebEnvironment.NONE)
@AutoConfigureWireMock(port=0)
@SpringBootTest(classes = WiremockTestsApplication.class,
properties = "app.baseUrl=http://localhost:${wiremock.server.port}", webEnvironment = WebEnvironment.NONE)
@AutoConfigureWireMock(port = 0)
// Default stubs work at classpath:/mappings
public class AutoConfigureWireMockAutoStubsApplicationTests {

View File

@@ -1,18 +1,19 @@
package org.springframework.cloud.contract.wiremock;
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.context.junit4.SpringRunner;
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.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes=WiremockTestsApplication.class, properties="app.baseUrl=https://localhost:${wiremock.server.https-port}", webEnvironment=WebEnvironment.NONE)
@AutoConfigureWireMock(port=0, httpsPort=0)
@@ -28,4 +29,4 @@ public class AutoConfigureWireMockRandomPortHttpsApplicationTests {
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}
}

View File

@@ -10,6 +10,7 @@ import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import org.assertj.core.api.BDDAssertions;
import org.junit.Test;
import org.junit.runner.RunWith;
import wiremock.org.eclipse.jetty.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
@@ -21,7 +22,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -32,8 +32,6 @@ import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.docu
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import wiremock.org.eclipse.jetty.http.HttpStatus;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfiguration.class)
@AutoConfigureRestDocs(outputDir = "target/snippets")

View File

@@ -1,10 +1,12 @@
package org.springframework.cloud.contract.wiremock;
import com.github.tomakehurst.wiremock.client.WireMock;
import org.junit.ComparisonFailure;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@@ -23,8 +25,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.github.tomakehurst.wiremock.client.WireMock;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfiguration.class)
@AutoConfigureRestDocs(outputDir = "target/snippets")