Adds support for execute in request body

fixes #313
This commit is contained in:
Marcin Grzejszczak
2017-06-01 17:50:10 +02:00
parent fe299de7c2
commit 4631ab6ea8
10 changed files with 92 additions and 12 deletions

View File

@@ -283,7 +283,6 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/org/springframework/cloud/contract/verifier/twitter/places/BaseMockMvcSpec.groovy[tags=base_class,indent=0]
----
IMPORTANT: You can't use both a String and `execute` to perform concatenation. E.g. calling
`header('Authorization', 'Bearer ' + execute('authToken()'))` will lead to improper results.
To make this work just call `header('Authorization', execute('authToken()'))` and ensure that
@@ -298,6 +297,36 @@ JSON path:
- proper `Number` if you point to `Integer`, `Double` etc. in a JSON
- `Boolean` if you point to a `Boolean` in a JSON
In the request part of the contract you can specify that the `body` should be
taken from a method.
IMPORTANT: You have to provide both the consumer and the producer side
and the `execute` part can be applied for the whole body. Not for parts of it!
Example:
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy[tags=body_execute,indent=0]
----
This will result in calling the `hashCode()` method in the request body.
It would more or less like this:
[source,java,indent=0]
----
// given:
MockMvcRequestSpecification request = given()
.body(hashCode());
// when:
ResponseOptions response = given().spec(request)
.get("/something");
// then:
assertThat(response.statusCode()).isEqualTo(200);
----
===== Referencing request from response
The best situation is to provide fixed values but sometimes you need to reference a request in your response.

View File

@@ -175,7 +175,7 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
}
@Override
protected String getBodyString(String bodyAsString) {
protected String getBodyString(Object body) {
return ""
}

View File

@@ -152,8 +152,14 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder
}
@Override
protected String getBodyString(String bodyAsString) {
return ".body(\"$bodyAsString\")"
protected String getBodyString(Object body) {
String value
if (body instanceof ExecutionProperty) {
value = body.toString()
} else {
value = "\"$body\""
}
return ".body($value)"
}
@Override

View File

@@ -104,7 +104,9 @@ class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
String method = request.method.serverValue.toString().toLowerCase()
if (request.body) {
String contentType = getHeader('Content-Type') ?: getRequestContentType().mimeType
bb.addLine(".method(\"${method.toUpperCase()}\", entity(\"$bodyAsString\", \"$contentType\"))")
String body = request.body?.serverValue instanceof ExecutionProperty ?
request.body?.serverValue?.toString() : "\"${bodyAsString}\""
bb.addLine(".method(\"${method.toUpperCase()}\", entity(${body}, \"$contentType\"))")
} else {
bb.addLine(".method(\"${method.toUpperCase()}\")")
}

View File

@@ -109,7 +109,9 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
String method = request.method.serverValue.toString().toLowerCase()
if (request.body) {
String contentType = getHeader('Content-Type') ?: getRequestContentType().mimeType
bb.addLine(".method('${method.toUpperCase()}', entity('$bodyAsString', '$contentType'))")
String body = request.body?.serverValue instanceof ExecutionProperty ?
request.body?.serverValue?.toString() : "'${bodyAsString}'"
bb.addLine(".method('${method.toUpperCase()}', entity(${body}, '$contentType'))")
} else {
bb.addLine(".method('${method.toUpperCase()}')")
}
@@ -123,7 +125,7 @@ class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequ
}
protected String getHeader(String name) {
return request.headers?.entries.find { it.name == name }?.serverValue
return request.headers?.entries?.find { it.name == name }?.serverValue
}
@Override

View File

@@ -197,7 +197,7 @@ abstract class MethodBodyBuilder {
/**
* Builds the code to append body to the request / message
*/
protected abstract String getBodyString(String bodyAsString)
protected abstract String getBodyString(Object body)
/**
* Builds the code to append multipart content to the request.

View File

@@ -98,7 +98,9 @@ abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
bb.addLine(getHeaderString(header))
}
if (request.body) {
bb.addLine(getBodyString(bodyAsString))
Object body = request.body?.serverValue instanceof ExecutionProperty ?
request.body?.serverValue : bodyAsString
bb.addLine(getBodyString(body))
}
if (request.multipart) {
multipartParameters?.each { Map.Entry<String, Object> entry -> bb.addLine(getMultipartParameterLine(entry)) }

View File

@@ -169,7 +169,7 @@ class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
}
@Override
protected String getBodyString(String bodyAsString) {
protected String getBodyString(Object body) {
return ''
}

View File

@@ -127,8 +127,14 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing
}
@Override
protected String getBodyString(String bodyAsString) {
return ".body('''$bodyAsString''')"
protected String getBodyString(Object body) {
String value
if (body instanceof ExecutionProperty) {
value = body.toString()
} else {
value = "'''$body'''"
}
return ".body($value)"
}
@Override

View File

@@ -207,4 +207,37 @@ DocumentContext parsedJson = JsonPath.parse(json);
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) }
}
@Issue('#313')
def "should allow to use execute in request body [#methodBuilderName]"() {
given:
//tag::body_execute[]
Contract contractDsl = Contract.make {
request {
method 'GET'
url '/something'
body(
$(c("foo"), p(execute("hashCode()")))
)
}
response {
status 200
}
}
//end::body_execute[]
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString())
!test.contains("executionCommand")
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) }
}
}