Merge branch '1.2.x'

This commit is contained in:
Marcin Grzejszczak
2018-03-09 16:57:23 +01:00
3 changed files with 95 additions and 8 deletions

View File

@@ -80,6 +80,10 @@
<groupId>com.github.jknack</groupId>
<artifactId>handlebars</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>

View File

@@ -16,15 +16,17 @@
package org.springframework.cloud.contract.verifier.builder
import java.util.regex.Pattern
import com.jayway.jsonpath.DocumentContext
import com.jayway.jsonpath.JsonPath
import com.jayway.jsonpath.PathNotFoundException
import groovy.json.JsonOutput
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import org.apache.commons.beanutils.PropertyUtilsBean
import org.apache.commons.text.StringEscapeUtils
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.spec.ContractTemplate
import org.springframework.cloud.contract.spec.internal.BodyMatcher
@@ -47,8 +49,6 @@ import org.springframework.cloud.contract.verifier.util.MapConverter
import org.springframework.util.SerializationUtils
import org.springframework.util.StringUtils
import java.util.regex.Pattern
import static org.springframework.cloud.contract.verifier.util.ContentUtils.extractValue
/**
* Main class for building method body.
@@ -64,6 +64,9 @@ import static org.springframework.cloud.contract.verifier.util.ContentUtils.extr
abstract class MethodBodyBuilder {
private static final Closure GET_SERVER_VALUE = { it instanceof DslProperty ? it.serverValue : it }
private static final String FROM_REQUEST_PREFIX = "request."
private static final String FROM_REQUEST_BODY = "body"
private static final String FROM_REQUEST_PATH = "path"
protected final ContractVerifierConfigProperties configProperties
protected final TemplateProcessor templateProcessor
@@ -332,11 +335,15 @@ abstract class MethodBodyBuilder {
processText(bb, "", convertedResponseBody)
addColonIfRequired(bb)
}
private void addJsonResponseBodyCheck(BlockBuilder bb, convertedResponseBody, BodyMatchers bodyMatchers) {
appendJsonPath(bb, getResponseAsString())
Object copiedBody = cloneBody(convertedResponseBody)
convertedResponseBody = JsonToJsonPathsConverter.removeMatchingJsonPaths(convertedResponseBody, bodyMatchers)
// remove quotes from fromRequest objects before picking json paths
TestSideRequestTemplateModel templateModel = contract.request?.body ?
TestSideRequestTemplateModel.from(contract.request) : null
convertedResponseBody = MapConverter.transformValues(convertedResponseBody, returnReferencedEntries(templateModel))
JsonPaths jsonPaths = new JsonToJsonPathsConverter(configProperties).transformToJsonPathWithTestsSideValues(convertedResponseBody)
DocumentContext parsedRequestBody
if (contract.request?.body) {
@@ -351,6 +358,14 @@ abstract class MethodBodyBuilder {
bb.addLine("assertThatJson(parsedJson)" + postProcessedMethod)
addColonIfRequired(bb)
}
doBodyMatchingIfPresent(bodyMatchers, bb, copiedBody)
if (!(convertedResponseBody instanceof Map || convertedResponseBody instanceof List)) {
simpleTextResponseBodyCheck(bb, convertedResponseBody)
}
processBodyElement(bb, "", "", convertedResponseBody)
}
private void doBodyMatchingIfPresent(BodyMatchers bodyMatchers, BlockBuilder bb, copiedBody) {
if (bodyMatchers?.hasMatchers()) {
bb.endBlock()
bb.addLine(addCommentSignIfRequired('and:'))
@@ -366,10 +381,35 @@ abstract class MethodBodyBuilder {
}
}
}
if (!(convertedResponseBody instanceof Map || convertedResponseBody instanceof List)) {
simpleTextResponseBodyCheck(bb, convertedResponseBody)
}
private Closure<Object> returnReferencedEntries(TestSideRequestTemplateModel templateModel) {
return { entry ->
if (!(entry instanceof String) || !templateModel) {
return entry
}
String entryAsString = (String) entry
if (templateProcessor.containsTemplateEntry(entryAsString) &&
!templateProcessor.containsJsonPathTemplateEntry(entryAsString)) {
String justEntry = entryAsString - contractTemplate.openingTemplate() -
contractTemplate.closingTemplate() - FROM_REQUEST_PREFIX
if (justEntry == FROM_REQUEST_BODY) {
// the body should be transformed by standard mechanism
return entry
}
try {
Object result = new PropertyUtilsBean().getProperty(templateModel, justEntry)
// Path from the Test model is an object and we'd like to return its String representation
if (justEntry == FROM_REQUEST_PATH) {
return result.toString()
}
return result
} catch (Exception e) {
return entry
}
}
return entry
}
processBodyElement(bb, "", "", convertedResponseBody)
}
protected String processIfTemplateIsPresent(String method, DocumentContext parsedRequestBody) {
@@ -383,6 +423,8 @@ abstract class MethodBodyBuilder {
.replace('"' + contractTemplate.openingTemplate(), contractTemplate.openingTemplate())
.replace(contractTemplate.closingTemplate() + '"', contractTemplate.closingTemplate())
}
} else if (templateProcessor.containsTemplateEntry(method)) {
}
return method
}

View File

@@ -380,6 +380,47 @@ DocumentContext parsedJson = JsonPath.parse(json);
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } | { String string -> string.contains('assertThat(responseBody).isEqualTo("My name");') }
}
@Issue("#559")
def "should reference request from body without escaping of non-string [#methodBuilderName]"() {
given:
Contract contractDsl = Contract.make {
request {
method 'GET'
url( '/mytest') {
queryParameters {
parameter("foo", "bar")
parameter("number", 1)
}
}
body("""{ "name": "My name" }""")
}
response {
status 200
body (
foo: fromRequest().query("foo"),
number: fromRequest().query("number")
)
}
}
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
String test = blockBuilder.toString()
SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test)
test.contains('''assertThatJson(parsedJson).field("['foo']").isEqualTo("bar")''')
test.contains('''assertThatJson(parsedJson).field("['number']").isEqualTo(1)''')
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) }
}
@Issue("#465")
def "should work for '/' url for [#methodBuilderName]"() {
given: