Added support for referencing the request
This commit is contained in:
@@ -23,6 +23,7 @@ import java.nio.file.Files
|
||||
import com.example.loan.model.Client
|
||||
import com.example.loan.model.LoanApplication
|
||||
import com.example.loan.model.LoanApplicationStatus
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.jayway.jsonpath.JsonPath
|
||||
import com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson
|
||||
import io.restassured.RestAssured
|
||||
@@ -145,4 +146,23 @@ class LoanApplicationServiceTests {
|
||||
assertThat(exchange.body).isEqualTo(Files.readAllBytes(response.toPath()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldSuccessfullyReturnRequestDataInResponse() {
|
||||
// when:
|
||||
val exchange: ResponseEntity<FraudCheckResponse> = RestTemplate().exchange(
|
||||
RequestEntity.put(URI.create("http://localhost:6565/frauds/name"))
|
||||
.header("Content-Type", "application/json")
|
||||
.body(FraudCheckRequest("Tim")),
|
||||
FraudCheckResponse::class.java)
|
||||
// then:
|
||||
assertThat(exchange.statusCodeValue).isEqualTo(200)
|
||||
assertThat(exchange.headers["Content-Type"]?.get(0))
|
||||
.isEqualTo("application/json")
|
||||
// and:
|
||||
assertThat(exchange.body?.message).isEqualTo("Don't worry Tim you're not a fraud")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class FraudCheckRequest(@JsonProperty("name") val name: String)
|
||||
data class FraudCheckResponse(@JsonProperty("result") val message: String)
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package fraudname
|
||||
|
||||
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
|
||||
import org.springframework.cloud.contract.spec.internal.HttpMethods
|
||||
import org.springframework.cloud.contract.spec.internal.HttpStatus
|
||||
|
||||
contract {
|
||||
// highest priority
|
||||
@@ -33,10 +31,9 @@ contract {
|
||||
}
|
||||
response {
|
||||
status = OK
|
||||
// TODO
|
||||
// body = body("result" to "Sorry ${fromRequest().body("$.name")} but you're a fraud")
|
||||
// headers {
|
||||
// header(contentType(), fromRequest().header(contentType()))
|
||||
// }
|
||||
body = body("result" to "Sorry ${fromRequest().body("$.name")} but you're a fraud")
|
||||
headers {
|
||||
contentType = fromRequest().header(CONTENT_TYPE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package fraudname
|
||||
|
||||
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
|
||||
import org.springframework.cloud.contract.spec.internal.HttpMethods
|
||||
import org.springframework.cloud.contract.spec.internal.HttpStatus
|
||||
|
||||
contract {
|
||||
request {
|
||||
@@ -31,10 +29,9 @@ contract {
|
||||
}
|
||||
response {
|
||||
status = OK
|
||||
// TODO
|
||||
// body("result" to "Don't worry ${fromRequest().body("$.name")} you're not a fraud")
|
||||
// headers {
|
||||
// header(contentType(), fromRequest().header(contentType()))
|
||||
// }
|
||||
body = body("result" to "Don't worry ${fromRequest().body("$.name")} you're not a fraud")
|
||||
headers {
|
||||
contentType = fromRequest().header(CONTENT_TYPE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* https://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.spec.internal
|
||||
|
||||
import org.springframework.cloud.contract.spec.ContractTemplate
|
||||
|
||||
/**
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
class FromRequestDsl {
|
||||
|
||||
private val template: ContractTemplate = HandlebarsContractTemplate()
|
||||
|
||||
/**
|
||||
* @return URL path and query.
|
||||
*/
|
||||
fun url() = FromRequestDslProperty(template.escapedUrl())
|
||||
|
||||
/**
|
||||
* First value of a query parameter e.g. request.query.search.
|
||||
* @param key key for the query param
|
||||
* @return dsl property
|
||||
*/
|
||||
fun query(key: String) = FromRequestDslProperty(template.escapedQuery(key))
|
||||
|
||||
/**
|
||||
* nth value of a query parameter (zero indexed) e.g. request.query.search.[5].
|
||||
* @param key key for the query param
|
||||
* @param index index of the query param
|
||||
* @return dsl property
|
||||
*/
|
||||
fun query(key: String, index: Int) = FromRequestDslProperty(template.escapedQuery(key, index))
|
||||
|
||||
/**
|
||||
* URL path.
|
||||
* @return dsl property
|
||||
*/
|
||||
fun path() = FromRequestDslProperty(template.escapedPath())
|
||||
|
||||
/**
|
||||
* nth value of a URL path (zero indexed) e.g. {{{ request.path.[2] }}}* @param index.
|
||||
* @param index path index
|
||||
* @return dsl property
|
||||
*/
|
||||
fun path(index: Int) = FromRequestDslProperty(template.escapedPath(index))
|
||||
|
||||
/**
|
||||
* First value of a request header e.g. request.headers.X-Request-Id.
|
||||
* @param key header key
|
||||
* @return dsl property
|
||||
*/
|
||||
fun header(key: String) = FromRequestDslProperty(template.escapedHeader(key))
|
||||
|
||||
/**
|
||||
* nth value of a request header (zero indexed) e.g. request.headers.X-Request-Id.
|
||||
* @param key header key
|
||||
* @param index header index
|
||||
* @return dsl property
|
||||
*/
|
||||
fun header(key: String, index: Int) = FromRequestDslProperty(template.escapedHeader(key, index))
|
||||
|
||||
/**
|
||||
* Retruns the tempalte for retrieving the first value of a cookie with certain key.
|
||||
* @param key cookie key
|
||||
* @return dsl property
|
||||
*/
|
||||
fun cookie(key: String) = FromRequestDslProperty(template.escapedCookie(key))
|
||||
|
||||
/**
|
||||
* Request body text (avoid for non-text bodies).
|
||||
* @return dsl property
|
||||
*/
|
||||
fun body() = FromRequestDslProperty(template.escapedBody())
|
||||
|
||||
/**
|
||||
* Request body text for the given JsonPath.
|
||||
* @param jsonPath json path body
|
||||
* @return dsl property
|
||||
*/
|
||||
fun body(jsonPath: String) = FromRequestDslProperty(template.escapedBody(jsonPath))
|
||||
|
||||
/**
|
||||
* Unescaped URL path and query.
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawUrl() = FromRequestDslProperty(template.url())
|
||||
|
||||
/**
|
||||
* Unescaped First value of a query parameter e.g. request.query.search.
|
||||
* @param key query key
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawQuery(key: String) = FromRequestDslProperty(template.query(key))
|
||||
|
||||
/**
|
||||
* Unescaped nth value of a query parameter (zero indexed) e.g.
|
||||
* request.query.search.[5].
|
||||
* @param key query key
|
||||
* @param index query index
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawQuery(key: String, index: Int) = FromRequestDslProperty(template.query(key, index))
|
||||
|
||||
/**
|
||||
* Unescaped URL path.
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawPath() = FromRequestDslProperty(template.path())
|
||||
|
||||
/**
|
||||
* Unescaped nth value of a URL path (zero indexed) e.g. {{{ request.path.[2]. }}}*
|
||||
* @param index path index
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawPath(index: Int) = FromRequestDslProperty(template.path(index))
|
||||
|
||||
/**
|
||||
* Unescaped First value of a request header e.g. request.headers.X-Request-Id.
|
||||
* @param key header key
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawHeader(key: String) = FromRequestDslProperty(template.header(key))
|
||||
|
||||
/**
|
||||
* Unescaped nth value of a request header (zero indexed) e.g.
|
||||
* request.headers.X-Request-Id.
|
||||
* @param key header key
|
||||
* @param index header index
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawHeader(key: String, index: Int) = FromRequestDslProperty(template.header(key, index))
|
||||
|
||||
/**
|
||||
* Unescaped Returns the template for retrieving the first value of a cookie with
|
||||
* certain key.
|
||||
* @param key cookie key
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawCookie(key: String) = FromRequestDslProperty(template.cookie(key))
|
||||
|
||||
/**
|
||||
* Unescaped Request body text (avoid for non-text bodies).
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawBody() = FromRequestDslProperty(template.body())
|
||||
|
||||
/**
|
||||
* Unescaped Request body text for the given JsonPath.
|
||||
* @param jsonPath json path body
|
||||
* @return dsl property
|
||||
*/
|
||||
fun rawBody(jsonPath: String) = FromRequestDslProperty(template.body(jsonPath))
|
||||
|
||||
}
|
||||
|
||||
class FromRequestDslProperty(private val content: String) : DslProperty<String>(content) {
|
||||
// Overridden to support String interpolation
|
||||
override fun toString(): String = content
|
||||
}
|
||||
@@ -275,6 +275,132 @@ open class HeadersDsl: CommonDsl() {
|
||||
|
||||
/* HELPER VARIABLES */
|
||||
|
||||
/* HTTP HEADERS */
|
||||
|
||||
val ACCEPT = HttpHeaders.ACCEPT
|
||||
|
||||
val ACCEPT_CHARSET = HttpHeaders.ACCEPT_CHARSET
|
||||
|
||||
val ACCEPT_ENCODING = HttpHeaders.ACCEPT_ENCODING
|
||||
|
||||
val ACCEPT_LANGUAGE = HttpHeaders.ACCEPT_LANGUAGE
|
||||
|
||||
val ACCEPT_RANGES = HttpHeaders.ACCEPT_RANGES
|
||||
|
||||
val ACCESS_CONTROL_ALLOW_CREDENTIALS = HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS
|
||||
|
||||
val ACCESS_CONTROL_ALLOW_HEADERS = HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS
|
||||
|
||||
val ACCESS_CONTROL_ALLOW_METHODS = HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS
|
||||
|
||||
val ACCESS_CONTROL_ALLOW_ORIGIN = HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN
|
||||
|
||||
val ACCESS_CONTROL_EXPOSE_HEADERS = HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS
|
||||
|
||||
val ACCESS_CONTROL_MAX_AGE = HttpHeaders.ACCESS_CONTROL_MAX_AGE
|
||||
|
||||
val ACCESS_CONTROL_REQUEST_HEADERS = HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS
|
||||
|
||||
val ACCESS_CONTROL_REQUEST_METHOD = HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD
|
||||
|
||||
val AGE = HttpHeaders.AGE
|
||||
|
||||
val ALLOW = HttpHeaders.ALLOW
|
||||
|
||||
val AUTHORIZATION = HttpHeaders.AUTHORIZATION
|
||||
|
||||
val CACHE_CONTROL = HttpHeaders.CACHE_CONTROL
|
||||
|
||||
val CONNECTION = HttpHeaders.CONNECTION
|
||||
|
||||
val CONTENT_ENCODING = HttpHeaders.CONTENT_ENCODING
|
||||
|
||||
val CONTENT_DISPOSITION = HttpHeaders.CONTENT_DISPOSITION
|
||||
|
||||
val CONTENT_LANGUAGE = HttpHeaders.CONTENT_LANGUAGE
|
||||
|
||||
val CONTENT_LENGTH = HttpHeaders.CONTENT_LENGTH
|
||||
|
||||
val CONTENT_LOCATION = HttpHeaders.CONTENT_LOCATION
|
||||
|
||||
val CONTENT_RANGE = HttpHeaders.CONTENT_RANGE
|
||||
|
||||
val CONTENT_TYPE = HttpHeaders.CONTENT_TYPE
|
||||
|
||||
val COOKIE = HttpHeaders.COOKIE
|
||||
|
||||
val DATE = HttpHeaders.DATE
|
||||
|
||||
val ETAG = HttpHeaders.ETAG
|
||||
|
||||
val EXPECT = HttpHeaders.EXPECT
|
||||
|
||||
val EXPIRES = HttpHeaders.EXPIRES
|
||||
|
||||
val FROM = HttpHeaders.FROM
|
||||
|
||||
val HOST = HttpHeaders.HOST
|
||||
|
||||
val IF_MATCH = HttpHeaders.IF_MATCH
|
||||
|
||||
val IF_MODIFIED_SINCE = HttpHeaders.IF_MODIFIED_SINCE
|
||||
|
||||
val IF_NONE_MATCH = HttpHeaders.IF_NONE_MATCH
|
||||
|
||||
val IF_RANGE = HttpHeaders.IF_RANGE
|
||||
|
||||
val IF_UNMODIFIED_SINCE = HttpHeaders.IF_UNMODIFIED_SINCE
|
||||
|
||||
val LAST_MODIFIED = HttpHeaders.LAST_MODIFIED
|
||||
|
||||
val LINK = HttpHeaders.LINK
|
||||
|
||||
val LOCATION = HttpHeaders.LOCATION
|
||||
|
||||
val MAX_FORWARDS = HttpHeaders.MAX_FORWARDS
|
||||
|
||||
val ORIGIN = HttpHeaders.ORIGIN
|
||||
|
||||
val PRAGMA = HttpHeaders.PRAGMA
|
||||
|
||||
val PROXY_AUTHENTICATE = HttpHeaders.PROXY_AUTHENTICATE
|
||||
|
||||
val PROXY_AUTHORIZATION = HttpHeaders.PROXY_AUTHORIZATION
|
||||
|
||||
val RANGE = HttpHeaders.RANGE
|
||||
|
||||
val REFERER = HttpHeaders.REFERER
|
||||
|
||||
val RETRY_AFTER = HttpHeaders.RETRY_AFTER
|
||||
|
||||
val SERVER = HttpHeaders.SERVER
|
||||
|
||||
val SET_COOKIE = HttpHeaders.SET_COOKIE
|
||||
|
||||
val SET_COOKIE_2 = HttpHeaders.SET_COOKIE_2
|
||||
|
||||
val TE = HttpHeaders.TE
|
||||
|
||||
val TRAILER = HttpHeaders.TRAILER
|
||||
|
||||
val TRANSFER_ENCODING = HttpHeaders.TRANSFER_ENCODING
|
||||
|
||||
val UPGRADE = HttpHeaders.UPGRADE
|
||||
|
||||
val USER_AGENT = HttpHeaders.USER_AGENT
|
||||
|
||||
val VARY = HttpHeaders.VARY
|
||||
|
||||
val VIA = HttpHeaders.VIA
|
||||
|
||||
val WARNING = HttpHeaders.WARNING
|
||||
|
||||
val WWW_AUTHENTICATE = HttpHeaders.WWW_AUTHENTICATE
|
||||
|
||||
/* MESSAGING HEADERS */
|
||||
|
||||
val MESSAGING_CONTENT_TYPE = MessagingHeaders.MESSAGING_CONTENT_TYPE
|
||||
|
||||
/* MEDIA TYPES */
|
||||
|
||||
val ALL_VALUE = MediaTypes.ALL_VALUE
|
||||
|
||||
@@ -229,8 +229,7 @@ class ResponseDsl : CommonDsl(), RegexCreatingProperty<ServerDslProperty> {
|
||||
|
||||
fun `$`(server: ServerDslProperty, client: ClientDslProperty) = delegate.value(client, server)
|
||||
|
||||
// TODO, needs to be reworked - no lazy string interpolation like in Groovy
|
||||
// fun fromRequest() = FromRequest()
|
||||
fun fromRequest() = FromRequestDsl()
|
||||
|
||||
override fun anyAlphaUnicode() = delegate.anyAlphaUnicode()
|
||||
|
||||
|
||||
@@ -881,4 +881,37 @@ then:
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should support fromRequest`() {
|
||||
val contract = contract {
|
||||
request {
|
||||
method = GET
|
||||
url = url("/path")
|
||||
body = body("id" to mapOf("value" to "132"))
|
||||
headers {
|
||||
accept = APPLICATION_JSON
|
||||
}
|
||||
}
|
||||
response {
|
||||
status = OK
|
||||
body = body("value is ${fromRequest().body("$.value")}")
|
||||
headers {
|
||||
contentType = fromRequest().header(ACCEPT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertDoesNotThrow {
|
||||
Contract.assertContract(contract)
|
||||
}.also {
|
||||
val response = contract.response
|
||||
assertThat(response.body.clientValue).isEqualTo("value is {{{jsonPath request.body '$.value'}}}")
|
||||
val headers = response.headers.entries
|
||||
assertThat(headers).hasSize(1)
|
||||
assertThat(headers.elementAt(0).name).isEqualTo("Content-Type")
|
||||
assertThat(headers.elementAt(0).clientValue).isEqualTo("{{{request.headers.Accept.[0]}}}")
|
||||
assertThat(headers.elementAt(0).serverValue).isEqualTo("{{{request.headers.Accept.[0]}}}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user