Merge branch '1.0.x'

fixes #179 #117
This commit is contained in:
Marcin Grzejszczak
2016-12-28 19:40:42 +01:00
14 changed files with 377 additions and 92 deletions

View File

@@ -289,6 +289,59 @@ org.springframework.cloud.contract.spec.Contract.make {
}
----
==== Working with Context Paths
Spring Cloud Contract supports context paths.
IMPORTANT: The only thing that changes in order to fully support context paths is the switch
on the *PRODUCER* side. The autogenerated tests need to be using the *EXPLICIT* mode.
The consumer side remains untouched, in order for the generated test to pass you have to switch the *EXPLICIT* mode.
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
.Maven
----
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<testMode>EXPLICIT</testMode>
</configuration>
</plugin>
----
[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
.Gradle
----
contracts {
testMode = 'EXPLICIT'
}
----
That way you'll generate a test that *DOES NOT* use MockMvc. It means that you're generating
real requests and you need to setup your generated test's base class to work on a real socket.
Let's imagine the following contract:
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy[tags=context_path_contract,indent=0]
----
Here is an example of how to set up a base class and Rest Assured for everything to work correctly.
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy[tags=context_path_baseclass,indent=0]
----
That way all:
- all your requests in the autogenerated tests will be sent to the real endpoint with your context path included (e.g. `/my-context-path/url`)
- your contracts reflect that you have a context path, thus your generated stubs will also
have that information (e.g. in the stubs you'll see that you have too call `/my-context-path/url`)
==== Messaging Top-Level Elements

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2013-2016 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.verifier.builder
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
/**
* A {@link JUnitMethodBodyBuilder} implementation that uses Rest Assured in explicit mode
*
* @author Marcin Grzejszczak
*
* @since 1.0.3
*/
@TypeChecked
@PackageScope
class ExplicitJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder {
ExplicitJUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties) {
super(stubDefinition, configProperties)
}
@Override
protected String returnedResponseType() {
return "Response"
}
@Override
protected String returnedRequestType() {
return "RequestSpecification"
}
}

View File

@@ -126,16 +126,24 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder
@Override
protected String getInputString(Request request) {
def inputString = 'ResponseOptions response = given().spec(request)'
def inputString = "${returnedResponseType()} response = given().spec(request)"
if (response.async){
inputString = inputString + '.when().async()'
}
return inputString
}
protected String returnedResponseType() {
return "ResponseOptions"
}
@Override
protected String getInputString() {
return 'MockMvcRequestSpecification request = given()'
return "${returnedRequestType()} request = given()"
}
protected String returnedRequestType() {
return "MockMvcRequestSpecification"
}
@Override

View File

@@ -83,6 +83,9 @@ class JavaTestGenerator implements SingleTestGenerator {
if (contracts.values().contains(TestType.HTTP) && configProperties.testMode == TestMode.MOCKMVC) {
clazz.addImport('com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification')
clazz.addImport('com.jayway.restassured.response.ResponseOptions')
} else if (contracts.values().contains(TestType.HTTP) && configProperties.testMode == TestMode.EXPLICIT) {
clazz.addImport('com.jayway.restassured.specification.RequestSpecification')
clazz.addImport('com.jayway.restassured.response.Response')
}
clazz.addImport('org.junit.Test')
clazz.addStaticImport('org.assertj.core.api.Assertions.assertThat')

View File

@@ -22,9 +22,9 @@ import groovy.util.logging.Slf4j
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
import org.springframework.cloud.contract.verifier.config.TestFramework
import org.springframework.cloud.contract.verifier.util.NamesUtil
import org.springframework.cloud.contract.verifier.config.TestMode
import org.springframework.cloud.contract.verifier.file.ContractMetadata
import org.springframework.cloud.contract.verifier.util.NamesUtil
/**
* Builds a test method. Adds an ignore annotation on a method if necessary.
@@ -92,21 +92,26 @@ class MethodBuilder {
private MethodBodyBuilder getMethodBodyBuilder() {
if (stubContent.input || stubContent.outputMessage) {
if (configProperties.targetFramework == TestFramework.JUNIT){
if (configProperties.targetFramework == TestFramework.JUNIT) {
return new JUnitMessagingMethodBodyBuilder(stubContent, configProperties)
}
return new SpockMessagingMethodBodyBuilder(stubContent, configProperties)
}
if (configProperties.testMode == TestMode.MOCKMVC && configProperties.targetFramework == TestFramework.JUNIT){
return new MockMvcJUnitMethodBodyBuilder(stubContent, configProperties)
}
if (configProperties.testMode == TestMode.JAXRSCLIENT) {
if (configProperties.targetFramework == TestFramework.JUNIT){
if (configProperties.targetFramework == TestFramework.JUNIT) {
return new JaxRsClientJUnitMethodBodyBuilder(stubContent, configProperties)
}
return new JaxRsClientSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties)
} else if (configProperties.testMode == TestMode.EXPLICIT) {
if (configProperties.targetFramework == TestFramework.JUNIT) {
return new ExplicitJUnitMethodBodyBuilder(stubContent, configProperties)
}
// in Groovy we're using def so we don't have to update the imports
return new MockMvcSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties)
} else if (configProperties.targetFramework == TestFramework.SPOCK) {
return new MockMvcSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties)
}
return new MockMvcSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties)
return new MockMvcJUnitMethodBodyBuilder(stubContent, configProperties)
}
}

View File

@@ -19,12 +19,8 @@ package org.springframework.cloud.contract.verifier.builder
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
import org.springframework.cloud.contract.spec.internal.Header
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
import java.util.regex.Pattern
/**
* A {@link JUnitMethodBodyBuilder} implementation that uses MockMvc to send requests.
*
@@ -34,55 +30,20 @@ import java.util.regex.Pattern
*/
@TypeChecked
@PackageScope
class MockMvcJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
class MockMvcJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder {
MockMvcJUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties) {
super(stubDefinition, configProperties)
}
@Override
protected void validateResponseCodeBlock(BlockBuilder bb) {
bb.addLine("assertThat(response.statusCode()).isEqualTo($response.status.serverValue);")
protected String returnedResponseType() {
return "ResponseOptions"
}
@Override
protected void validateResponseHeadersBlock(BlockBuilder bb) {
response.headers?.executeForEachHeader { Header header ->\
processHeaderElement(bb, header.name, header.serverValue)
}
}
@Override
protected String getResponseBodyPropertyComparisonString(String property, Object value) {
return null
}
@Override
protected String getResponseBodyPropertyComparisonString(String property, Pattern value) {
return null
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
if (value instanceof NotToEscapePattern) {
blockBuilder.addLine("assertThat(response.header(\"$property\"))." +
"${createMatchesMethod(value.serverValue.pattern().replace("\\", "\\\\"))};")
}
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(value)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(pattern)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
blockBuilder.addLine("${exec.insertValue("response.header(\"$property\")")};")
protected String returnedRequestType() {
return "MockMvcRequestSpecification"
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright 2013-2016 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.verifier.builder
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
import org.springframework.cloud.contract.spec.internal.Header
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
import java.util.regex.Pattern
/**
* A {@link JUnitMethodBodyBuilder} implementation that uses Rest Assured.
*
* @author Marcin Grzejszczak
*
* @since 1.0.3
*/
@TypeChecked
@PackageScope
class RestAssuredJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
RestAssuredJUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties) {
super(stubDefinition, configProperties)
}
@Override
protected void validateResponseCodeBlock(BlockBuilder bb) {
bb.addLine("assertThat(response.statusCode()).isEqualTo($response.status.serverValue);")
}
@Override
protected void validateResponseHeadersBlock(BlockBuilder bb) {
response.headers?.executeForEachHeader { Header header ->\
processHeaderElement(bb, header.name, header.serverValue)
}
}
@Override
protected String getResponseBodyPropertyComparisonString(String property, Object value) {
return null
}
@Override
protected String getResponseBodyPropertyComparisonString(String property, Pattern value) {
return null
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
if (value instanceof NotToEscapePattern) {
blockBuilder.addLine("assertThat(response.header(\"$property\"))." +
"${createMatchesMethod(value.serverValue.pattern().replace("\\", "\\\\"))};")
}
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(value)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
blockBuilder.addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(pattern)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
blockBuilder.addLine("${exec.insertValue("response.header(\"$property\")")};")
}
}

View File

@@ -1,7 +1,7 @@
/*
* Copyright 2013-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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
*
@@ -21,6 +21,7 @@ import org.junit.rules.TemporaryFolder
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
import org.springframework.cloud.contract.verifier.config.TestMode
import org.springframework.cloud.contract.verifier.file.ContractMetadata
import org.springframework.cloud.contract.verifier.util.SyntaxChecker
import spock.lang.Issue
import spock.lang.Specification
@@ -34,16 +35,44 @@ class SingleTestGeneratorSpec extends Specification {
TemporaryFolder tmpFolder = new TemporaryFolder()
File file
static List<String> jUnitClassStrings = ['package test;', 'import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;',
'import org.junit.FixMethodOrder;', 'import org.junit.Ignore;', 'import org.junit.Test;', 'import org.junit.runners.MethodSorters;',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*;',
'@FixMethodOrder(MethodSorters.NAME_ASCENDING)', '@Test', '@Ignore', 'mport com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification;',
'import com.jayway.restassured.response.ResponseOptions;', 'import static org.assertj.core.api.Assertions.assertThat;']
private static final List<String> mockMvcJUnitClassStrings = ['package test; ', 'import com.jayway.jsonpath.DocumentContext; ', 'import com.jayway.jsonpath.JsonPath; ',
'import org.junit.FixMethodOrder; ', 'import org.junit.Ignore; ', 'import org.junit.Test; ', 'import org.junit.runners.MethodSorters; ',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; ', 'import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*; ',
'@FixMethodOrder(MethodSorters.NAME_ASCENDING); ', '@Test; ', '@Ignore; ', 'import com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification; ',
'import com.jayway.restassured.response.ResponseOptions; ', 'import static org.assertj.core.api.Assertions.assertThat']
static List<String> spockClassStrings = ['package test', 'import com.jayway.jsonpath.DocumentContext', 'import com.jayway.jsonpath.JsonPath',
'import spock.lang.Ignore', 'import spock.lang.Specification', 'import spock.lang.Stepwise',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson', 'import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*',
'@Stepwise', '@Ignore']
private static final List<String> explicitJUnitClassStrings = ['package test; ', 'import com.jayway.jsonpath.DocumentContext; ', 'import com.jayway.jsonpath.JsonPath; ',
'import org.junit.FixMethodOrder; ', 'import org.junit.Ignore; ', 'import org.junit.Test; ', 'import org.junit.runners.MethodSorters; ',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; ', 'import static com.jayway.restassured.RestAssured.*; ',
'@FixMethodOrder(MethodSorters.NAME_ASCENDING); ', '@Test; ', '@Ignore; ', 'import com.jayway.restassured.specification.RequestSpecification; ',
'import com.jayway.restassured.response.Response; ', 'import static org.assertj.core.api.Assertions.assertThat']
private static final List<String> spockClassStrings = ['package test', 'import com.jayway.jsonpath.DocumentContext', 'import com.jayway.jsonpath.JsonPath',
'import spock.lang.Ignore', 'import spock.lang.Specification', 'import spock.lang.Stepwise',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson', 'import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*',
'@Stepwise', '@Ignore']
private static final List<String> explicitSpockClassStrings = ['package test', 'import com.jayway.jsonpath.DocumentContext', 'import com.jayway.jsonpath.JsonPath',
'import spock.lang.Ignore', 'import spock.lang.Specification', 'import spock.lang.Stepwise',
'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson', 'import static com.jayway.restassured.RestAssured.*',
'@Stepwise', '@Ignore']
public static final Closure JAVA_ASSERTER = { String classToTest ->
String name = Math.abs(new Random().nextInt())
String changedTest = classToTest.replace("public class Test", "public class Test${name}")
SyntaxChecker.tryToCompileJavaWithoutImports("test.Test${name}", changedTest)
}
public static final Closure JAVA_JAXRS_ASSERTER = { String classToTest ->
String name = Math.abs(new Random().nextInt())
String changedTest = classToTest.replace("public class Test {", "public class Test${name} {\njavax.ws.rs.client.WebTarget webTarget;\n")
SyntaxChecker.tryToCompileJavaWithoutImports("test.Test${name}", changedTest)
}
public static final Closure GROOVY_ASSERTER = { String classToTest ->
SyntaxChecker.tryToCompileGroovyWithoutImports(classToTest)
}
def setup() {
file = tmpFolder.newFile()
@@ -60,9 +89,9 @@ class SingleTestGeneratorSpec extends Specification {
""")
}
def "should build MockMvc test class for #testFramework"() {
def "should build test class for #testFramework"() {
given:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties();
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.targetFramework = testFramework
ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 2, convertAsCollection(file))
contract.ignored >> true
@@ -74,16 +103,19 @@ class SingleTestGeneratorSpec extends Specification {
then:
classStrings.each { clazz.contains(it) }
and:
asserter(clazz)
where:
testFramework | classStrings
JUNIT | jUnitClassStrings
SPOCK | spockClassStrings
testFramework | mode | classStrings | asserter
JUNIT | TestMode.MOCKMVC | mockMvcJUnitClassStrings | JAVA_ASSERTER
JUNIT | TestMode.EXPLICIT | explicitJUnitClassStrings | JAVA_ASSERTER
SPOCK | TestMode.MOCKMVC | spockClassStrings | GROOVY_ASSERTER
SPOCK | TestMode.EXPLICIT | explicitSpockClassStrings | GROOVY_ASSERTER
}
def "should build JaxRs test class for #testFramework"() {
given:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties();
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.testMode = TestMode.JAXRSCLIENT
properties.targetFramework = testFramework
ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 2, convertAsCollection(file))
@@ -97,10 +129,13 @@ class SingleTestGeneratorSpec extends Specification {
then:
classStrings.each { clazz.contains(it) }
and:
asserter(clazz)
where:
testFramework | classStrings
JUNIT | ['import static javax.ws.rs.client.Entity.*;', 'import javax.ws.rs.core.Response;']
SPOCK | ['import static javax.ws.rs.client.Entity.*;']
testFramework | classStrings | asserter
JUNIT | ['import static javax.ws.rs.client.Entity.*', 'import javax.ws.rs.core.Response'] | JAVA_JAXRS_ASSERTER
SPOCK | ['import static javax.ws.rs.client.Entity.*'] | GROOVY_ASSERTER
}
def "should work if there is messaging and rest in one folder #testFramework"() {
@@ -117,12 +152,12 @@ class SingleTestGeneratorSpec extends Specification {
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
assertThat('hashCode()')
}
}
""")
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties();
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.targetFramework = testFramework
ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 2, convertAsCollection(file))
contract.ignored >> true
@@ -141,10 +176,13 @@ class SingleTestGeneratorSpec extends Specification {
classStrings.each { clazz.contains(it) }
clazz.contains('@Inject ContractVerifierMessaging')
and:
asserter(clazz)
where:
testFramework | classStrings
JUNIT | jUnitClassStrings
SPOCK | spockClassStrings
testFramework | classStrings | asserter
JUNIT | mockMvcJUnitClassStrings | JAVA_ASSERTER
SPOCK | spockClassStrings | GROOVY_ASSERTER
}
@Issue('#30')
@@ -164,7 +202,7 @@ class SingleTestGeneratorSpec extends Specification {
}
""")
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties();
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.targetFramework = testFramework
and:
ContractMetadata contract2 = new ContractMetadata(secondFile.toPath(), true, 1, 2, convertAsCollection(file))
@@ -180,10 +218,68 @@ class SingleTestGeneratorSpec extends Specification {
classStrings.each { clazz.contains(it) }
clazz.contains('@Ignore')
and:
asserter(clazz)
where:
testFramework | classStrings
JUNIT | jUnitClassStrings
SPOCK | spockClassStrings
testFramework | classStrings | asserter
JUNIT | mockMvcJUnitClassStrings | JAVA_ASSERTER
SPOCK | spockClassStrings | GROOVY_ASSERTER
}
@Issue('#117')
def "should generate test in explicit test mode using JUnit"() {
given:
String baseClass = """
// tag::context_path_baseclass[]
import com.jayway.restassured.RestAssured;
import org.junit.Before;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = ContextPathTestingBaseClass.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ContextPathTestingBaseClass {
@LocalServerPort int port;
@Before
public void setup() {
RestAssured.baseURI = "http://localhost";
RestAssured.port = this.port;
}
}
// end::context_path_baseclass[]
"""
SyntaxChecker.tryToCompileJavaWithoutImports("test.ContextPathTestingBaseClass", "package test;\n${baseClass}")
and:
File secondFile = tmpFolder.newFile()
secondFile.write("""
// tag::context_path_contract[]
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'GET'
url '/my-context-path/url'
}
response {
status 200
}
}
// end::context_path_contract[]
""")
and:
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
properties.targetFramework = JUNIT
properties.testMode = TestMode.EXPLICIT
properties.baseClassForTests = "test.ContextPathTestingBaseClass"
and:
ContractMetadata contract = new ContractMetadata(file.toPath(), false, 1, null)
and:
SingleTestGenerator testGenerator = new SingleTestGenerator(properties)
when:
String clazz = testGenerator.buildClass([contract], "test", "test", 'com/foo')
then:
clazz.contains("RequestSpecification request = given();")
clazz.contains("Response response = given().spec(request)")
}
def "should pick the contract's name as the test method"() {

View File

@@ -43,7 +43,7 @@ class SyntaxChecker {
].collect { "import static ${it};"}.join("\n")
public static void tryToCompile(String builderName, String test) {
static void tryToCompile(String builderName, String test) {
if (builderName.toLowerCase().contains("spock")) {
tryToCompileGroovy(test)
} else {
@@ -51,7 +51,7 @@ class SyntaxChecker {
}
}
public static void tryToCompileGroovy(String test) {
static void tryToCompileGroovy(String test) {
def imports = new ImportCustomizer()
CompilerConfiguration configuration = new CompilerConfiguration()
configuration.addCompilationCustomizers(imports)
@@ -65,7 +65,7 @@ class SyntaxChecker {
new GroovyShell(SyntaxChecker.classLoader, configuration).parse(sourceCode.toString())
}
public static Class tryToCompileJava(String test) {
static Class tryToCompileJava(String test) {
Random random = new Random()
int first = Math.abs(random.nextInt())
int hashCode = Math.abs(test.hashCode())
@@ -76,15 +76,25 @@ class SyntaxChecker {
sourceCode.append("${DEFAULT_IMPORTS_AS_STRING}\n")
sourceCode.append("${STATIC_IMPORTS}\n")
sourceCode.append("\n")
sourceCode.append("public class ${className} {\n")
sourceCode.append("class ${className} {\n")
sourceCode.append("\n")
sourceCode.append(" WebTarget webTarget;")
sourceCode.append("\n")
sourceCode.append(" public void method() {\n")
sourceCode.append(" void method() {\n")
sourceCode.append(" ${test}\n")
sourceCode.append(" }\n")
sourceCode.append("}")
return InMemoryJavaCompiler.compile(fqnClassName, sourceCode.toString())
}
static boolean tryToCompileJavaWithoutImports(String fqn, String test) {
InMemoryJavaCompiler.compile(fqn, test)
return true
}
static boolean tryToCompileGroovyWithoutImports(String test) {
new GroovyShell(SyntaxChecker.classLoader).parse(test)
return true
}
}

View File

@@ -4,12 +4,14 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.embedded.LocalServerPort;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.contract.stubrunner.StubFinder;
import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import com.example.loan.model.Client;
import com.example.loan.model.LoanApplication;
@@ -20,19 +22,28 @@ import static org.assertj.core.api.Assertions.assertThat;
// tag::autoconfigure_stubrunner[]
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.NONE)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
@AutoConfigureStubRunner(repositoryRoot = "classpath:m2repo/repository/",
ids = { "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer" })
ids = { "org.springframework.cloud.contract.verifier.stubs:contextPathFraudDetectionServer" })
@DirtiesContext
public class LoanApplicationServiceTests {
// end::autoconfigure_stubrunner[]
@Autowired private LoanApplicationService service;
@Autowired private StubFinder stubFinder;
@LocalServerPort Integer port;
@Before
public void setPort() {
this.service.setFraudUrl(this.stubFinder.findStubUrl("fraudDetectionServer").toString());
this.service.setFraudUrl(this.stubFinder.findStubUrl("contextPathFraudDetectionServer").toString() + "/fraud-path/");
}
@Test
public void shouldStartThisAppWithContextPath() {
String response = new RestTemplate()
.getForObject("http://localhost:" + this.port + "/my-path/health", String.class);
assertThat(response).isNotEmpty();
}
@Test

View File

@@ -19,7 +19,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud.contract.verifier.stubs</groupId>
<artifactId>fraudDetectionServer</artifactId>
<artifactId>contextPathFraudDetectionServer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
</project>

View File

@@ -17,7 +17,7 @@
<metadata>
<groupId>org.springframework.cloud.contract.verifier.stubs</groupId>
<artifactId>fraudDetectionServer</artifactId>
<artifactId>contextPathFraudDetectionServer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<versioning>
<versions>