Upgraded to Greenwhich
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<artifactId>groovy</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
42
pom.xml
42
pom.xml
@@ -26,17 +26,17 @@
|
||||
<checkstyle.version>2.17</checkstyle.version>
|
||||
<pact.version>3.5.13</pact.version>
|
||||
<jsch-agent.version>0.0.9</jsch-agent.version>
|
||||
<spring-cloud-build.version>2.0.4.BUILD-SNAPSHOT</spring-cloud-build.version>
|
||||
<spring-cloud-zookeeper.version>2.0.0.BUILD-SNAPSHOT</spring-cloud-zookeeper.version>
|
||||
<spring-cloud-stream.version>Elmhurst.BUILD-SNAPSHOT</spring-cloud-stream.version>
|
||||
<spring-cloud-netflix.version>2.0.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
|
||||
<spring-cloud-consul.version>2.0.0.BUILD-SNAPSHOT</spring-cloud-consul.version>
|
||||
<spring-cloud-commons.version>2.0.0.BUILD-SNAPSHOT</spring-cloud-commons.version>
|
||||
<spring-cloud-build.version>2.1.0.BUILD-SNAPSHOT</spring-cloud-build.version>
|
||||
<spring-cloud-zookeeper.version>2.1.0.BUILD-SNAPSHOT</spring-cloud-zookeeper.version>
|
||||
<spring-cloud-stream.version>Fishtown.BUILD-SNAPSHOT</spring-cloud-stream.version>
|
||||
<spring-cloud-netflix.version>2.1.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
|
||||
<spring-cloud-consul.version>2.1.0.BUILD-SNAPSHOT</spring-cloud-consul.version>
|
||||
<spring-cloud-commons.version>2.1.0.BUILD-SNAPSHOT</spring-cloud-commons.version>
|
||||
<jopt-simple.version>5.0.3</jopt-simple.version>
|
||||
<cglib.version>3.2.4</cglib.version>
|
||||
<spock-spring.version>1.0-groovy-2.4</spock-spring.version>
|
||||
<spock-global-unroll.version>0.5.1</spock-global-unroll.version>
|
||||
<spring-rabbit.version>2.0.0.RELEASE</spring-rabbit.version>
|
||||
<spring-rabbit.version>2.1.0.M2</spring-rabbit.version>
|
||||
<hoverfly-junit.version>0.2.2</hoverfly-junit.version>
|
||||
<commons-text.version>1.1</commons-text.version>
|
||||
<handlebars.version>4.0.6</handlebars.version>
|
||||
@@ -83,11 +83,31 @@
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-spring</artifactId>
|
||||
<version>${spock-spring.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-core</artifactId>
|
||||
<version>${spock-spring.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>info.solidsoft.spock</groupId>
|
||||
@@ -118,6 +138,10 @@
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -129,6 +153,10 @@
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.3.RELEASE</version>
|
||||
<version>2.1.0.M1</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.3.RELEASE</version>
|
||||
<version>2.1.0.M1</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.3.RELEASE</version>
|
||||
<version>2.1.0.M1</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.3.RELEASE</version>
|
||||
<version>2.1.0.M1</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.3.RELEASE</version>
|
||||
<version>2.1.0.M1</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ class Url extends DslProperty {
|
||||
url.values.collect { it instanceof Pattern ?
|
||||
new Xeger(it.pattern()).generate() : it
|
||||
} as String[],
|
||||
url.strings.clone() as String[]
|
||||
Arrays.copyOf(url.strings, url.strings.length) as String[]
|
||||
).toString()
|
||||
return new Url(newUrl)
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.springframework.context.annotation.Import;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import({HttpStubsController.class, TriggerController.class, StreamConfiguration.class, StubRunnerConfiguration.class})
|
||||
@Import({HttpStubsController.class, TriggerController.class, StubRunnerConfiguration.class})
|
||||
public @interface EnableStubRunnerServer {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.springframework.cloud.contract.stubrunner.server;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.stream.test.binder.MessageCollector;
|
||||
import org.springframework.cloud.stream.test.binder.TestSupportBinder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
/**
|
||||
* Configuration required to make Stub Runner server be executed at compile time
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
class StreamConfiguration {
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
@ConditionalOnClass(name = "org.springframework.cloud.stream.test.binder.TestSupportBinder")
|
||||
@ConditionalOnMissingBean
|
||||
public MessageCollector messageCollector() {
|
||||
return new TestSupportBinder().messageCollector();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,13 +17,16 @@
|
||||
package org.springframework.cloud.contract.stubrunner.server;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.stream.config.BindingServiceConfiguration;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableStubRunnerServer
|
||||
@AutoConfigureBefore(BindingServiceConfiguration.class)
|
||||
public class StubRunnerBoot {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -3,7 +3,6 @@ org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner=\
|
||||
org.springframework.cloud.contract.stubrunner.spring.StubRunnerConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.spring.cloud.StubRunnerSpringCloudAutoConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.spring.cloud.ribbon.StubRunnerRibbonAutoConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.messaging.stream.StubRunnerStreamConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.messaging.integration.StubRunnerIntegrationConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.spring.cloud.zookeeper.StubRunnerSpringCloudZookeeperAutoConfiguration,\
|
||||
org.springframework.cloud.contract.stubrunner.spring.cloud.eureka.StubRunnerSpringCloudEurekaAutoConfiguration,\
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier
|
||||
import org.springframework.cloud.stream.annotation.EnableBinding
|
||||
import org.springframework.cloud.stream.messaging.Sink
|
||||
import org.springframework.cloud.stream.messaging.Source
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.core.env.Environment
|
||||
import org.springframework.http.ResponseEntity
|
||||
@@ -86,6 +87,6 @@ class StubRunnerStubsPerConsumerSpec extends Specification {
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableBinding(Sink)
|
||||
@EnableBinding([Sink, Source])
|
||||
static class Config {}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties
|
||||
import org.springframework.cloud.contract.verifier.messaging.MessageVerifier
|
||||
import org.springframework.cloud.stream.annotation.EnableBinding
|
||||
import org.springframework.cloud.stream.messaging.Sink
|
||||
import org.springframework.cloud.stream.messaging.Source
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.core.env.Environment
|
||||
import org.springframework.http.ResponseEntity
|
||||
@@ -87,6 +88,6 @@ class StubRunnerStubsPerConsumerWithConsumerNameSpec extends Specification {
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableBinding(Sink)
|
||||
@EnableBinding([Sink, Source])
|
||||
static class Config {}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ ext {
|
||||
]
|
||||
}
|
||||
|
||||
project.version = findProperty('verifierVersion') ?: '2.0.0.BUILD-SNAPSHOT'
|
||||
project.version = findProperty('verifierVersion') ?: '2.1.0.BUILD-SNAPSHOT'
|
||||
apply plugin: 'groovy'
|
||||
apply from: "$rootDir/gradle/release.gradle"
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
@@ -36,7 +36,9 @@ dependencies {
|
||||
|
||||
testCompile "com.github.tomakehurst:wiremock:${wiremockVersion}"
|
||||
testCompile "com.toomuchcoding.jsonassert:jsonassert:${jsonAssertVersion}"
|
||||
testCompile "org.spockframework:spock-spring:1.0-groovy-2.4"
|
||||
testCompile("org.spockframework:spock-spring:1.0-groovy-2.4") {
|
||||
exclude(group: 'org.codehaus.groovy')
|
||||
}
|
||||
testCompile "io.restassured:rest-assured:$restAssuredVersion"
|
||||
testCompile "io.restassured:spring-mock-mvc:$restAssuredVersion"
|
||||
testCompile "ch.qos.logback:logback-classic:1.1.2"
|
||||
|
||||
@@ -52,7 +52,9 @@ subprojects {
|
||||
|
||||
dependencies {
|
||||
testCompile 'org.codehaus.groovy:groovy-all:2.5.0-beta-1'
|
||||
testCompile "org.spockframework:spock-core:$spockVersion"
|
||||
testCompile("org.spockframework:spock-core:$spockVersion") {
|
||||
exclude(group: 'org.codehaus.groovy')
|
||||
}
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile "com.github.tomakehurst:wiremock:${wiremockVersion}"
|
||||
testCompile "com.toomuchcoding.jsonassert:jsonassert:${jsonAssertVersion}"
|
||||
@@ -81,7 +83,9 @@ configure([project(':fraudDetectionService'), project(':loanApplicationService')
|
||||
compile 'org.springframework.boot:spring-boot-starter-jersey'
|
||||
compile 'org.springframework.boot:spring-boot-starter-jetty'
|
||||
|
||||
testRuntime "org.spockframework:spock-spring:$spockVersion"
|
||||
testRuntime("org.spockframework:spock-spring:$spockVersion") {
|
||||
exclude(group: 'org.codehaus.groovy')
|
||||
}
|
||||
|
||||
testCompile "org.mockito:mockito-core"
|
||||
testCompile "org.springframework:spring-test"
|
||||
|
||||
@@ -48,7 +48,9 @@ subprojects {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile "org.codehaus.groovy:groovy-all:2.5.0-beta-1"
|
||||
testCompile("org.codehaus.groovy:groovy-all:2.5.0-beta-1") {
|
||||
exclude(group: 'org.codehaus.groovy')
|
||||
}
|
||||
testCompile "org.spockframework:spock-core:$spockVersion"
|
||||
testCompile("junit:junit:4.12")
|
||||
testCompile "com.github.tomakehurst:wiremock:${wiremockVersion}"
|
||||
@@ -89,7 +91,9 @@ configure([project(':fraudDetectionService'), project(':loanApplicationService')
|
||||
compile("org.springframework.boot:spring-boot-starter-jetty")
|
||||
compile("org.springframework.boot:spring-boot-starter-actuator")
|
||||
|
||||
testRuntime "org.spockframework:spock-spring:$spockVersion"
|
||||
testRuntime("org.spockframework:spock-spring:$spockVersion") {
|
||||
exclude(group: 'org.codehaus.groovy')
|
||||
}
|
||||
testCompile "org.mockito:mockito-core"
|
||||
testCompile "org.springframework:spring-test"
|
||||
testCompile "org.springframework.boot:spring-boot-test"
|
||||
|
||||
@@ -50,7 +50,9 @@ subprojects {
|
||||
|
||||
dependencies {
|
||||
testCompile "org.codehaus.groovy:groovy-all:2.5.0-beta-1"
|
||||
testCompile "org.spockframework:spock-core:$spockVersion"
|
||||
testCompile("org.spockframework:spock-core:$spockVersion") {
|
||||
exclude(group: 'org.codehaus.groovy')
|
||||
}
|
||||
testCompile "junit:junit:4.12"
|
||||
testCompile "com.github.tomakehurst:wiremock:${wiremockVersion}"
|
||||
testCompile "com.toomuchcoding.jsonassert:jsonassert:${jsonAssertVersion}"
|
||||
@@ -113,7 +115,9 @@ configure([project(':fraudDetectionService'), project(':loanApplicationService')
|
||||
compile("org.springframework.boot:spring-boot-starter-jetty")
|
||||
compile("org.springframework.boot:spring-boot-starter-actuator")
|
||||
|
||||
testRuntime "org.spockframework:spock-spring:$spockVersion"
|
||||
testRuntime("org.spockframework:spock-spring:$spockVersion") {
|
||||
exclude(group: 'org.codehaus.groovy')
|
||||
}
|
||||
testCompile "org.mockito:mockito-core"
|
||||
testCompile "org.springframework:spring-test"
|
||||
testCompile "org.springframework.boot:spring-boot-test"
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@Immutable
|
||||
@CompileStatic
|
||||
class TestSideRequestTemplateModel {
|
||||
/**
|
||||
@@ -50,6 +49,15 @@ class TestSideRequestTemplateModel {
|
||||
*/
|
||||
final String escapedBody
|
||||
|
||||
private TestSideRequestTemplateModel(String url, Map<String, List<String>> query, Path path, Map<String, List<String>> headers, String body, String escapedBody) {
|
||||
this.url = url
|
||||
this.query = query
|
||||
this.path = path
|
||||
this.headers = headers
|
||||
this.body = body
|
||||
this.escapedBody = escapedBody
|
||||
}
|
||||
|
||||
static TestSideRequestTemplateModel from(final Request request) {
|
||||
String url = MapConverter.getTestSideValues(request.url ?: request.urlPath)
|
||||
Path paths = new Path(buildPathsFromUrl(url))
|
||||
@@ -63,7 +71,11 @@ class TestSideRequestTemplateModel {
|
||||
Map<String, List<String>> headers = (Map<String, List<String>>) (request.headers?.entries?.groupBy {
|
||||
it.name
|
||||
}?.collectEntries {
|
||||
[(it.key): it.value.collect { MapConverter.getTestSideValues(it) }]
|
||||
List<Object> headerValues = []
|
||||
for (Object value : it.value) {
|
||||
headerValues.add(MapConverter.getTestSideValues(value))
|
||||
}
|
||||
[(it.key): headerValues]
|
||||
})
|
||||
String escapedBody = trimmedAndEscapedBody(request.body)
|
||||
String body = getBodyAsRawJson(request.body)
|
||||
@@ -94,7 +106,7 @@ class TestSideRequestTemplateModel {
|
||||
|
||||
protected static Object extractServerValueFromBody(bodyValue) {
|
||||
if (bodyValue instanceof GString) {
|
||||
bodyValue = ContentUtils.extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue })
|
||||
bodyValue = ContentUtils.extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue } as Closure)
|
||||
} else {
|
||||
bodyValue = MapConverter.transformValues(bodyValue, {
|
||||
it instanceof DslProperty ? it.serverValue : it
|
||||
|
||||
@@ -68,14 +68,16 @@ class ContractFileScanner {
|
||||
|
||||
private Set<PathMatcher> processPatterns(Set<String> patterns) {
|
||||
FileSystem fileSystem = FileSystems.getDefault()
|
||||
return patterns.collect({
|
||||
String syntaxAndPattern = MATCH_PREFIX + '**' + File.separator + it
|
||||
Set<PathMatcher> pathMatchers = new HashSet<PathMatcher>()
|
||||
for (String pattern : patterns) {
|
||||
String syntaxAndPattern = MATCH_PREFIX + '**' + File.separator + pattern
|
||||
// FIXME: This looks strange, need to be checked on windows
|
||||
if (IS_OS_WINDOWS) {
|
||||
syntaxAndPattern = syntaxAndPattern.replace("\\", "\\\\")
|
||||
}
|
||||
fileSystem.getPathMatcher(syntaxAndPattern)
|
||||
}) as Set
|
||||
pathMatchers.add(fileSystem.getPathMatcher(syntaxAndPattern))
|
||||
}
|
||||
return pathMatchers
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,35 +16,73 @@
|
||||
|
||||
package org.springframework.cloud.contract.wiremock.restdocs;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
|
||||
import com.github.tomakehurst.wiremock.common.Gzip;
|
||||
import com.github.tomakehurst.wiremock.http.ContentTypeHeader;
|
||||
import com.github.tomakehurst.wiremock.http.Cookie;
|
||||
import com.github.tomakehurst.wiremock.http.HttpHeader;
|
||||
import com.github.tomakehurst.wiremock.http.HttpHeaders;
|
||||
import com.github.tomakehurst.wiremock.http.QueryParameter;
|
||||
import com.github.tomakehurst.wiremock.http.Request;
|
||||
import com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter;
|
||||
|
||||
import com.github.tomakehurst.wiremock.http.RequestMethod;
|
||||
import com.github.tomakehurst.wiremock.servlet.WireMockHttpServletMultipartAdapter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.ResultHandler;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import wiremock.com.google.common.base.Function;
|
||||
import wiremock.com.google.common.base.Joiner;
|
||||
import wiremock.com.google.common.base.Optional;
|
||||
import wiremock.com.google.common.collect.FluentIterable;
|
||||
import wiremock.com.google.common.collect.ImmutableList;
|
||||
import wiremock.com.google.common.collect.ImmutableMultimap;
|
||||
import wiremock.com.google.common.collect.Maps;
|
||||
import wiremock.org.eclipse.jetty.util.MultiPartInputStreamParser;
|
||||
|
||||
public class ContractResultHandler extends
|
||||
WireMockVerifyHelper<MvcResult, ContractResultHandler> implements ResultHandler {
|
||||
import static com.github.tomakehurst.wiremock.common.Encoding.encodeBase64;
|
||||
import static com.github.tomakehurst.wiremock.common.Exceptions.throwUnchecked;
|
||||
import static com.github.tomakehurst.wiremock.common.Strings.stringFromBytes;
|
||||
import static com.github.tomakehurst.wiremock.common.Urls.splitQuery;
|
||||
import static java.util.Collections.list;
|
||||
import static wiremock.com.google.common.base.Charsets.UTF_8;
|
||||
import static wiremock.com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static wiremock.com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static wiremock.com.google.common.collect.FluentIterable.from;
|
||||
import static wiremock.com.google.common.collect.Lists.newArrayList;
|
||||
import static wiremock.com.google.common.io.ByteStreams.toByteArray;
|
||||
|
||||
public class ContractResultHandler
|
||||
extends WireMockVerifyHelper<MvcResult, ContractResultHandler>
|
||||
implements ResultHandler {
|
||||
|
||||
static final String ATTRIBUTE_NAME_CONFIGURATION = "org.springframework.restdocs.configuration";
|
||||
|
||||
@Override
|
||||
public void handle(MvcResult result) throws Exception {
|
||||
@Override public void handle(MvcResult result) throws Exception {
|
||||
configure(result);
|
||||
MockMvcRestDocumentation.document(getName()).handle(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResponseDefinitionBuilder getResponseDefinition(MvcResult result) {
|
||||
@Override protected ResponseDefinitionBuilder getResponseDefinition(
|
||||
MvcResult result) {
|
||||
MockHttpServletResponse response = result.getResponse();
|
||||
ResponseDefinitionBuilder definition;
|
||||
try {
|
||||
@@ -66,11 +104,9 @@ public class ContractResultHandler extends
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> getConfiguration(MvcResult result) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) result.getRequest()
|
||||
.getAttribute(ATTRIBUTE_NAME_CONFIGURATION);
|
||||
@Override protected Map<String, Object> getConfiguration(MvcResult result) {
|
||||
@SuppressWarnings("unchecked") Map<String, Object> map = (Map<String, Object>) result
|
||||
.getRequest().getAttribute(ATTRIBUTE_NAME_CONFIGURATION);
|
||||
if (map == null) {
|
||||
map = new HashMap<>();
|
||||
result.getRequest().setAttribute(ATTRIBUTE_NAME_CONFIGURATION, map);
|
||||
@@ -78,18 +114,15 @@ public class ContractResultHandler extends
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Request getWireMockRequest(MvcResult result) {
|
||||
@Override protected Request getWireMockRequest(MvcResult result) {
|
||||
return new WireMockHttpServletRequestAdapter(result.getRequest());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MediaType getContentType(MvcResult result) {
|
||||
@Override protected MediaType getContentType(MvcResult result) {
|
||||
return MediaType.valueOf(result.getRequest().getContentType());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] getRequestBodyContent(MvcResult result) {
|
||||
@Override protected byte[] getRequestBodyContent(MvcResult result) {
|
||||
try {
|
||||
return StreamUtils.copyToByteArray(result.getRequest().getInputStream());
|
||||
}
|
||||
@@ -99,3 +132,259 @@ public class ContractResultHandler extends
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// COPIED FROM WIREMOCK
|
||||
class WireMockHttpServletRequestAdapter implements Request {
|
||||
|
||||
private static final String ORIGINAL_REQUEST_KEY = "wiremock.ORIGINAL_REQUEST";
|
||||
|
||||
private final HttpServletRequest request;
|
||||
private byte[] cachedBody;
|
||||
private Collection<Part> cachedMultiparts;
|
||||
|
||||
WireMockHttpServletRequestAdapter(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override public String getUrl() {
|
||||
String url = this.request.getRequestURI();
|
||||
String contextPath = this.request.getContextPath();
|
||||
if (!isNullOrEmpty(contextPath) && url.startsWith(contextPath)) {
|
||||
url = url.substring(contextPath.length());
|
||||
}
|
||||
return withQueryStringIfPresent(url);
|
||||
}
|
||||
|
||||
@Override public String getAbsoluteUrl() {
|
||||
return withQueryStringIfPresent(this.request.getRequestURL().toString());
|
||||
}
|
||||
|
||||
private String withQueryStringIfPresent(String url) {
|
||||
return url + (isNullOrEmpty(this.request.getQueryString()) ?
|
||||
"" :
|
||||
"?" + this.request.getQueryString());
|
||||
}
|
||||
|
||||
@Override public RequestMethod getMethod() {
|
||||
return RequestMethod.fromString(this.request.getMethod().toUpperCase());
|
||||
}
|
||||
|
||||
@Override public String getScheme() {
|
||||
return this.request.getScheme();
|
||||
}
|
||||
|
||||
@Override public String getHost() {
|
||||
return this.request.getServerName();
|
||||
}
|
||||
|
||||
@Override public int getPort() {
|
||||
return this.request.getServerPort();
|
||||
}
|
||||
|
||||
@Override public String getClientIp() {
|
||||
String forwardedForHeader = this.getHeader("X-Forwarded-For");
|
||||
|
||||
if (forwardedForHeader != null && forwardedForHeader.length() > 0) {
|
||||
return forwardedForHeader;
|
||||
}
|
||||
|
||||
return this.request.getRemoteAddr();
|
||||
}
|
||||
|
||||
// Something's wrong with reading the body from request
|
||||
@Override public byte[] getBody() {
|
||||
if (this.cachedBody == null || this.cachedBody.length == 0) {
|
||||
try {
|
||||
if (this.request instanceof MockHttpServletRequest) {
|
||||
this.cachedBody = ((MockHttpServletRequest) this.request).getContentAsByteArray();
|
||||
return this.cachedBody;
|
||||
}
|
||||
byte[] body = toByteArray(this.request.getInputStream());
|
||||
boolean isGzipped = hasGzipEncoding() || Gzip.isGzipped(body);
|
||||
this.cachedBody = isGzipped ? Gzip.unGzip(body) : body;
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
return this.cachedBody;
|
||||
}
|
||||
|
||||
private Charset encodingFromContentTypeHeaderOrUtf8() {
|
||||
ContentTypeHeader contentTypeHeader = contentTypeHeader();
|
||||
if (contentTypeHeader != null) {
|
||||
return contentTypeHeader.charset();
|
||||
}
|
||||
return UTF_8;
|
||||
}
|
||||
|
||||
private boolean hasGzipEncoding() {
|
||||
String encodingHeader = this.request.getHeader("Content-Encoding");
|
||||
return encodingHeader != null && encodingHeader.contains("gzip");
|
||||
}
|
||||
|
||||
@Override public String getBodyAsString() {
|
||||
return stringFromBytes(getBody(), encodingFromContentTypeHeaderOrUtf8());
|
||||
}
|
||||
|
||||
@Override public String getBodyAsBase64() {
|
||||
return encodeBase64(getBody());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") @Override public String getHeader(String key) {
|
||||
List<String> headerNames = list(this.request.getHeaderNames());
|
||||
for (String currentKey : headerNames) {
|
||||
if (currentKey.toLowerCase().equals(key.toLowerCase())) {
|
||||
return this.request.getHeader(currentKey);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @SuppressWarnings("unchecked") public HttpHeader header(String key) {
|
||||
List<String> headerNames = list(this.request.getHeaderNames());
|
||||
for (String currentKey : headerNames) {
|
||||
if (currentKey.toLowerCase().equals(key.toLowerCase())) {
|
||||
List<String> valueList = list(this.request.getHeaders(currentKey));
|
||||
if (valueList.isEmpty()) {
|
||||
return HttpHeader.empty(key);
|
||||
}
|
||||
return new HttpHeader(key, valueList);
|
||||
}
|
||||
}
|
||||
|
||||
return HttpHeader.absent(key);
|
||||
}
|
||||
|
||||
@Override public ContentTypeHeader contentTypeHeader() {
|
||||
return getHeaders().getContentTypeHeader();
|
||||
}
|
||||
|
||||
@Override public boolean containsHeader(String key) {
|
||||
return header(key).isPresent();
|
||||
}
|
||||
|
||||
@Override public HttpHeaders getHeaders() {
|
||||
List<HttpHeader> headerList = newArrayList();
|
||||
for (String key : getAllHeaderKeys()) {
|
||||
headerList.add(header(key));
|
||||
}
|
||||
|
||||
return new HttpHeaders(headerList);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") @Override public Set<String> getAllHeaderKeys() {
|
||||
LinkedHashSet<String> headerKeys = new LinkedHashSet<>();
|
||||
for (Enumeration<String> headerNames = this.request.getHeaderNames(); headerNames
|
||||
.hasMoreElements(); ) {
|
||||
headerKeys.add(headerNames.nextElement());
|
||||
}
|
||||
|
||||
return headerKeys;
|
||||
}
|
||||
|
||||
@Override public Map<String, Cookie> getCookies() {
|
||||
ImmutableMultimap.Builder<String, String> builder = ImmutableMultimap.builder();
|
||||
javax.servlet.http.Cookie[] cookies = firstNonNull(this.request.getCookies(),
|
||||
new javax.servlet.http.Cookie[0]);
|
||||
for (javax.servlet.http.Cookie cookie : cookies) {
|
||||
builder.put(cookie.getName(), cookie.getValue());
|
||||
}
|
||||
return Maps.transformValues(builder.build().asMap(),
|
||||
input -> new Cookie(null, ImmutableList.copyOf(input)));
|
||||
}
|
||||
|
||||
@Override public QueryParameter queryParameter(String key) {
|
||||
return firstNonNull((splitQuery(this.request.getQueryString()).get(key)),
|
||||
QueryParameter.absent(key));
|
||||
}
|
||||
|
||||
@Override public boolean isBrowserProxyRequest() {
|
||||
if (!isJetty()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override @SuppressWarnings("unchecked") public Collection<Part> getParts() {
|
||||
if (!isMultipart()) {
|
||||
return null;
|
||||
}
|
||||
if (this.cachedMultiparts == null) {
|
||||
try {
|
||||
String contentTypeHeaderValue = FluentIterable
|
||||
.from(contentTypeHeader().values()).join(Joiner.on(" "));
|
||||
InputStream inputStream = new ByteArrayInputStream(getBody());
|
||||
MultiPartInputStreamParser inputStreamParser = new MultiPartInputStreamParser(
|
||||
inputStream, contentTypeHeaderValue, null, null);
|
||||
this.cachedMultiparts = from(safelyGetRequestParts())
|
||||
.transform(
|
||||
(Function<javax.servlet.http.Part, Part>) WireMockHttpServletMultipartAdapter::from).toList();
|
||||
}
|
||||
catch (IOException | ServletException exception) {
|
||||
return throwUnchecked(exception, Collection.class);
|
||||
}
|
||||
}
|
||||
return (this.cachedMultiparts.size() > 0) ? this.cachedMultiparts : null;
|
||||
}
|
||||
|
||||
private Collection<javax.servlet.http.Part> safelyGetRequestParts()
|
||||
throws IOException, ServletException {
|
||||
try {
|
||||
return this.request.getParts();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
if (ioe.getMessage().contains("Missing content for multipart")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean isMultipart() {
|
||||
String header = getHeader("Content-Type");
|
||||
return (header != null && header.contains("multipart"));
|
||||
}
|
||||
|
||||
@Override public Part getPart(final String name) {
|
||||
if (name == null || name.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
if (this.cachedMultiparts == null) {
|
||||
if (getParts() == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return from(this.cachedMultiparts).firstMatch(
|
||||
input -> name.equals(input.getName())).get();
|
||||
}
|
||||
|
||||
@Override public Optional<Request> getOriginalRequest() {
|
||||
Request originalRequest = (Request) this.request.getAttribute(ORIGINAL_REQUEST_KEY);
|
||||
return Optional.fromNullable(originalRequest);
|
||||
}
|
||||
|
||||
private boolean isJetty() {
|
||||
try {
|
||||
getClass("org.eclipse.jetty.server.Request");
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void getClass(String type) throws ClassNotFoundException {
|
||||
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
|
||||
ClassLoader loader = contextCL == null ?
|
||||
com.github.tomakehurst.wiremock.servlet.WireMockHttpServletRequestAdapter.class
|
||||
.getClassLoader() :
|
||||
contextCL;
|
||||
Class.forName(type, false, loader);
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return this.request.toString() + getBodyAsString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ public abstract class WireMockVerifyHelper<T, S extends WireMockVerifyHelper<T,
|
||||
if (this.builder != null) {
|
||||
this.builder.willReturn(getResponseDefinition(result));
|
||||
StubMapping stubMapping = this.builder.build();
|
||||
MatchResult match = stubMapping.getRequest()
|
||||
.match(getWireMockRequest(result));
|
||||
Request request = getWireMockRequest(result);
|
||||
MatchResult match = stubMapping.getRequest().match(request);
|
||||
assertThat(match.isExactMatch()).as("wiremock did not match request")
|
||||
.isTrue();
|
||||
configuration.put("contract.stubMapping", stubMapping);
|
||||
|
||||
@@ -50,7 +50,7 @@ public class WiremockServerRestDocsMatcherApplicationTests {
|
||||
|
||||
@Test
|
||||
public void doesNotMatch() throws Exception {
|
||||
this.expected.expect(ComparisonFailure.class);
|
||||
this.expected.expect(AssertionError.class);
|
||||
this.expected.expectMessage("wiremock did not match");
|
||||
this.mockMvc.perform(MockMvcRequestBuilders.post("/resource").content("greeting")
|
||||
.contentType(MediaType.TEXT_PLAIN))
|
||||
|
||||
Reference in New Issue
Block a user