Updated docs

This commit is contained in:
Tim Ysewyn
2019-08-13 14:34:06 +02:00
parent 5ae10f246c
commit c5d7936a7c
21 changed files with 804 additions and 17 deletions

View File

@@ -21,6 +21,7 @@
:verifier_root_path: {core_path}/spring-cloud-contract-verifier
:contract_spec_path: {core_path}/specs/spring-cloud-contract-spec-java
:contract_spec_tests_path: {core_path}/specs/spring-cloud-contract-spec
:contract_kotlin_spec_path: {core_path}/specs/spring-cloud-contract-spec-kotlin
:samples_path: {core_path}/samples
:verifier_core_path: {verifier_root_path}
:stubrunner_core_path: {core_path}/spring-cloud-contract-stub-runner

View File

@@ -7,6 +7,7 @@ Spring Cloud Contract supports the DSLs written in the following languages:
* Groovy
* YAML
* Java
* Kotlin
TIP: Spring Cloud Contract supports defining multiple contracts in a single file.
@@ -30,6 +31,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract_rest.yml[indent=0]
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest.java[tags=class,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_rest.kts[tags=class,indent=0]
----
====
[TIP]
@@ -89,6 +96,17 @@ contracts {
----
====
[[contract-kotlin]]
=== Contract DSL in Kotlin
To get started with writing contracts in Kotlin you would need to start with a (newly created) Kotlin Script file (.kts).
Just like the with the Java DSL you can put your contracts in any directory of your choice.
The Maven and Gradle plugins will look at the `src/test/resources/contracts` directory by default.
IMPORTANT: Remember that, inside the Kotlin Script file, you have to provide the fully qualified name to the `ContractDSL` class.
Generally you would use its contract function like this: `org.springframework.cloud.contract.spec.ContractDsl.contract { ... }`.
You can also provide an import to the `contract` function (`import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract`) and then call `contract { ... }`.
[[contract-limitations]]
=== Limitations
@@ -136,6 +154,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract_rest.yml[indent=0]
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=description,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=description,indent=0]
----
====
[[contract-dsl-name]]
@@ -171,6 +195,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=name,inde
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=name,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=name,indent=0]
----
====
[[contract-dsl-ignoring-contracts]]
@@ -198,6 +228,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=ignored,i
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=ignored,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=ignored,indent=0]
----
====
[[contract-dsl-in-progress]]
@@ -228,6 +264,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=in_progre
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=in_progress,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=in_progress,indent=0]
----
====
You can set the value of the `failOnInProgress` Spring Cloud Contract plugin property to ensure that your build will break when at least one contract in progress remains in your sources.
@@ -269,6 +311,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract_from_file.yml[inde
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_from_file.java[tags=class,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/readFromFile.kts[tags=class,indent=0]
----
====
Further assume that the JSON files is as follows:
@@ -314,6 +362,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract_pdf.yml[indent=0]
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_from_pdf.java[tags=class,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{contract_kotlin_spec_path}/src/test/resources/contracts/shouldWorkWithBinaryPayload.kts[tags=class,indent=0]
----
====
IMPORTANT: You should use this approach whenever you want to work with binary payloads,
@@ -362,6 +416,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=response,
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=http_dsl,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=http_dsl,indent=0]
----
====
IMPORTANT: If you want to make your contract have a higher priority,
@@ -394,6 +454,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request_o
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=request,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=request,indent=0]
----
====
You can specify an absolute rather than a relative `url`, but using `urlPath` is
@@ -419,6 +485,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract_rest_with_path.yml
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=url,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=url,indent=0]
----
====
`request` may contain query parameters, as the following example (which uses `urlPath`) shows:
@@ -443,6 +515,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=query_par
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=urlpath,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=urlpath,indent=0]
----
====
`request` can contain additional request headers, as the following example shows:
@@ -467,6 +545,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=headers,i
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=headers,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=headers,indent=0]
----
====
`request` may contain additional request cookies, as the following example shows:
@@ -491,6 +575,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=cookies,i
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=cookies,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=cookies,indent=0]
----
====
`request` may contain a request body, as the following example shows:
@@ -515,6 +605,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=body,inde
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=body,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=body,indent=0]
----
====
`request` can contain multipart elements. To include multipart elements, use the
@@ -538,6 +634,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract_multipart.yml[inde
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_multipart.java[tags=class,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/multipart.kts[tags=class,indent=0]
----
====
In the preceding example, we define parameters in either of two ways:
@@ -618,6 +720,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=response_
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=response,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=response,indent=0]
----
====
Besides status, the response may contain headers, cookies, and a body, which are
@@ -706,6 +814,12 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=regex,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=regex,indent=0]
----
====
You can also provide only one side of the communication with a regular expression. If you
@@ -744,13 +858,22 @@ All of those methods start with the `any` prefix, as follows:
include::{contract_spec_path}/src/main/java/org/springframework/cloud/contract/spec/internal/RegexCreatingProperty.java[tags=regex_creating_props,indent=0]
----
The following example shows how you can reference those methods (example for Groovy DSL):
The following example shows how you can reference those methods:
[source,groovy,indent=0]
====
[source,groovy,indent=0,role="primary"]
.groovy
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=regex_creating_props,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=regex_creating_props,indent=0]
----
====
[[contract-dsl-regex-limitations]]
===== Limitations
@@ -788,6 +911,12 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=optionals,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=optionals,indent=0]
----
====
By wrapping a part of the body with the `optional()` method, you create a regular
@@ -833,6 +962,12 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=method,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=method,indent=0]
----
====
The following code shows the base class portion of the test case:
@@ -978,6 +1113,37 @@ class shouldReturnStatsForAUser implements Supplier<Contract> {
}
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
package contracts.beer.rest
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
contract {
request {
method = method("POST")
url = url("/stats")
body(mapOf(
"name" to anyAlphaUnicode
))
headers {
contentType = APPLICATION_JSON
}
}
response {
status = OK
body(mapOf(
"text" to "Don't worry ${fromRequest().body("$.name")} thanks for your interested in drinking beer",
"quantity" to v(c(5), p(anyNumber))
))
headers {
contentType = fromRequest().header(CONTENT_TYPE)
}
}
}
----
====
Running a JUnit test generation leads to a test that resembles the following example:
@@ -1401,6 +1567,22 @@ class contract implements Supplier<Collection<Contract>> {
}
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
contract {
request {
// ...
}
response {
async = true
// ...
}
}
----
====
You can also use the `fixedDelayMilliseconds` method or property to add delay to your stubs.
@@ -1450,6 +1632,22 @@ class contract implements Supplier<Collection<Contract>> {
}
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
contract {
request {
// ...
}
response {
delay = fixedMilliseconds(1000)
// ...
}
}
----
====
[[contract-dsl-xml]]
@@ -1482,6 +1680,12 @@ include::{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml
----
include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_xml.java[tags=class,indent=0]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
include::{verifier_core_path}/src/test/resources/kotlin/contract_xml.kts[tags=class,indent=0]
----
====
The following example shows an automatically generated test for XML in the response body:
@@ -1555,6 +1759,25 @@ class contract implements Supplier<Collection<Contract>> {
}
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.kotlin
----
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
arrayOf(
contract {
name("should post a user")
// ...
},
contract {
// ...
},
contract {
// ...
}
}
----
====
In the preceding example, one contract has the `name` field and the other does not. This

View File

@@ -19,6 +19,7 @@ package fraud
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
import org.springframework.cloud.contract.spec.internal.HttpStatus
// tag::contract[]
contract {
request {
method = PUT
@@ -41,3 +42,4 @@ contract {
}
}
}
// end::contract[]

View File

@@ -39,7 +39,7 @@ class ResponseDsl : CommonDsl() {
fun code(code: Int): DslProperty<Any> = code.toDslProperty()
fun fixedMilliseconds(delay: Long) = delay.toDslProperty()
fun fixedMilliseconds(delay: Long): DslProperty<Any> = delay.toDslProperty()
fun headers(headers: HeadersDsl.() -> Unit) {
this.headers = ResponseHeadersDsl().apply(headers).get()

View File

@@ -214,8 +214,11 @@ class ContractTests {
@Test
fun `should set a description`() {
val contract = contract {
description = """
val contract =
// @formatter: off
// tag::description[]
contract {
description = """
given:
An input
when:
@@ -223,8 +226,9 @@ when:
then:
Output
"""
}
}
// end::description[]
// @formatter: on
assertDoesNotThrow {
Contract.assertContract(contract)
}.also {
@@ -241,9 +245,12 @@ then:
@Test
fun `should set a name`() {
val contract = contract {
val contract =
// tag::name[]
contract {
name = "some_special_name"
}
// end::name[]
assertDoesNotThrow {
Contract.assertContract(contract)
@@ -254,9 +261,12 @@ then:
@Test
fun `should mark a contract ignored`() {
val contract = contract {
val contract =
// tag::ignored[]
contract {
ignored = true
}
// end::ignored[]
assertDoesNotThrow {
Contract.assertContract(contract)
@@ -267,9 +277,12 @@ then:
@Test
fun `should mark a contract in progress`() {
val contract = contract {
val contract =
// tag::in_progress[]
contract {
inProgress = true
}
// end::in_progress[]
assertDoesNotThrow {
Contract.assertContract(contract)

View File

@@ -16,8 +16,8 @@
package contracts
//tag::class[]
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
import org.springframework.cloud.contract.spec.internal.HttpMethods
contract {
request {
@@ -36,3 +36,4 @@ contract {
}
}
}
//end::class[]

View File

@@ -15,6 +15,7 @@
* limitations under the License.
*/
// tag::class[]
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -68,4 +69,4 @@ class contract_multipart implements Supplier<Collection<Contract>> {
}
}
// end::class[]
// end::class[]

View File

@@ -15,6 +15,7 @@
* limitations under the License.
*/
// tag::class[]
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;
@@ -69,4 +70,4 @@ class contract_rest implements Supplier<Collection<Contract>> {
}
}
// end::class[]
// end::class[]

View File

@@ -15,6 +15,7 @@
* limitations under the License.
*/
// tag::class[]
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;
@@ -39,4 +40,4 @@ class contract_rest_from_file implements Supplier<Collection<Contract>> {
}
}
// end::class[]
// end::class[]

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
//tag::class[]
// tag::class[]
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;
@@ -45,4 +45,4 @@ class contract_rest_from_pdf implements Supplier<Collection<Contract>> {
}
}
// end::class[]
// end::class[]

View File

@@ -15,6 +15,7 @@
* limitations under the License.
*/
// tag::class[]
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;
@@ -102,4 +103,4 @@ class contract_rest_with_tags implements Supplier<Collection<Contract>> {
}
}
// end::class[]
// end::class[]

View File

@@ -15,6 +15,7 @@
* limitations under the License.
*/
// tag::class[]
import java.util.function.Supplier;
import org.springframework.cloud.contract.spec.Contract;
@@ -64,3 +65,4 @@ class contract_xml implements Supplier<Contract> {
};
}
// end::class[]

View File

@@ -0,0 +1,329 @@
/*
* 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 contracts
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
import org.springframework.cloud.contract.spec.withQueryParameters
var httpDsl: org.springframework.cloud.contract.spec.Contract =
// tag::http_dsl[]
contract {
// Definition of HTTP request part of the contract
// (this can be a valid request or invalid depending
// on type of contract being specified).
request {
method = GET
url = url("/foo")
// ...
}
// Definition of HTTP response part of the contract
// (a service implementing this contract should respond
// with following response after receiving request
// specified in "request" part above).
response {
status = OK
// ...
}
// Contract priority, which can be used for overriding
// contracts (1 is highest). Priority is optional.
priority = 1
}
// end::http_dsl[]
var request: org.springframework.cloud.contract.spec.Contract =
// tag::request[]
contract {
request {
// HTTP request method (GET/POST/PUT/DELETE).
method = method("GET")
// Path component of request URL is specified as follows.
urlPath = path("/users")
}
response {
// ...
status = code(200)
}
}
// end::request[]
var url: org.springframework.cloud.contract.spec.Contract =
// tag::url[]
contract {
request {
method = GET
// Specifying `url` and `urlPath` in one contract is illegal.
url("http://localhost:8888/users")
}
response {
// ...
status = OK
}
}
// end::url[]
var urlPaths: org.springframework.cloud.contract.spec.Contract =
// tag::urlpath[]
contract {
request {
// ...
method = GET
// Each parameter is specified in form
// `'paramName' : paramValue` where parameter value
// may be a simple literal or one of matcher functions,
// all of which are used in this example.
urlPath = path("/users") withQueryParameters {
// If a simple literal is used as value
// default matcher function is used (equalTo)
parameter("limit", 100)
// `equalTo` function simply compares passed value
// using identity operator (==).
parameter("filter", equalTo("email"))
// `containing` function matches strings
// that contains passed substring.
parameter("gender", value(consumer(containing("[mf]")), producer("mf")))
// `matching` function tests parameter
// against passed regular expression.
parameter("offset", value(consumer(matching("[0-9]+")), producer(123)))
// `notMatching` functions tests if parameter
// does not match passed regular expression.
parameter("loginStartsWith", value(consumer(notMatching(".{0,2}")), producer(3)))
}
// ...
}
response {
// ...
status = code(200)
}
}
// end::urlpath[]
var headers: org.springframework.cloud.contract.spec.Contract =
// tag::headers[]
contract {
request {
// ...
method = GET
url = url("/foo")
// Each header is added in form `'Header-Name' : 'Header-Value'`.
// there are also some helper variables
headers {
header("key", "value")
contentType = APPLICATION_JSON
}
// ...
}
response {
// ...
status = OK
}
}
// end::headers[]
var cookies: org.springframework.cloud.contract.spec.Contract =
// tag::cookies[]
contract {
request {
// ...
method = GET
url = url("/foo")
// Each Cookies is added in form `'Cookie-Key' : 'Cookie-Value'`.
// there are also some helper methods
cookies {
cookie("key", "value")
cookie("another_key", "another_value")
}
// ...
}
response {
// ...
status = code(200)
}
}
// end::cookies[]
var body: org.springframework.cloud.contract.spec.Contract =
// tag::body[]
contract {
request {
// ...
method = GET
url = url("/foo")
// Currently only JSON format of request body is supported.
// Format will be determined from a header or body's content.
body = body("{ \"login\" : \"john\", \"name\": \"John The Contract\" }")
}
response {
// ...
status = OK
}
}
// end::body[]
var response: org.springframework.cloud.contract.spec.Contract =
// tag::response[]
contract {
request {
// ...
method = GET
url =url("/foo")
}
response {
// Status code sent by the server
// in response to request specified above.
status = OK
}
}
// end::response[]
var regex: org.springframework.cloud.contract.spec.Contract =
// tag::regex[]
contract {
request {
method = method("GET")
url = url(v(consumer(regex("\\/[0-9]{2}")), producer("/12")))
}
response {
status = OK
body(mapOf(
"id" to v(anyNumber),
"surname" to v(consumer("Kowalsky"), producer(regex("[a-zA-Z]+")))
))
headers {
header("Content-Type", "text/plain")
}
}
}
// end::regex[]
var regexCreatingProps: org.springframework.cloud.contract.spec.Contract =
// tag::regex_creating_props[]
contract {
name = "foo"
label = "trigger_event"
input {
triggeredBy = "toString()"
}
outputMessage {
sentTo = sentTo("topic.rateablequote")
body(mapOf(
"alpha" to v(anyAlphaUnicode),
"number" to v(anyNumber),
"anInteger" to v(anyInteger),
"positiveInt" to v(anyPositiveInt),
"aDouble" to v(anyDouble),
"aBoolean" to v(aBoolean),
"ip" to v(anyIpAddress),
"hostname" to v(anyAlphaUnicode),
"email" to v(anyEmail),
"url" to v(anyUrl),
"httpsUrl" to v(anyHttpsUrl),
"uuid" to v(anyUuid),
"date" to v(anyDate),
"dateTime" to v(anyDateTime),
"time" to v(anyTime),
"iso8601WithOffset" to v(anyIso8601WithOffset),
"nonBlankString" to v(anyNonBlankString),
"nonEmptyString" to v(anyNonEmptyString),
"anyOf" to v(anyOf('foo', 'bar'))
))
headers {
header("Content-Type", "text/plain")
}
}
}
//end::regex_creating_props[]
var optionals: org.springframework.cloud.contract.spec.Contract =
// tag::optionals[]
contract { c ->
priority = 1
name = "optionals"
request {
method = POST
url = url("/users/password")
headers {
contentType = APPLICATION_JSON
}
body = body(mapOf(
"email" to v(consumer(optional(regex(email))), producer("abc@abc.com")),
"callback_url" to v(consumer(regex(hostname)), producer("https://partners.com"))
))
}
response {
status = NOT_FOUND
headers {
header("Content-Type", "application/json")
}
body(mapOf(
"code" to value(consumer("123123"), producer(optional("123123")))
))
}
}
// end::optionals[]
var methodDsl: org.springframework.cloud.contract.spec.Contract =
contract { c ->
request {
// tag::method[]
method = GET
// end::method[]
url = url("/foo")
}
response {
status = NOT_FOUND
}
priority = 1
}
var method: org.springframework.cloud.contract.spec.Contract =
// tag::methodBuilder[]
contract {
request {
method = PUT
url = url(v(consumer(regex("^/api/[0-9]{2}$")), producer("/api/12")))
headers {
header("Content-Type", "application/json")
}
body = body("[{\"text\": \"Gonna see you at Warsaw\" }]")
}
response {
status = OK
body = body(mapOf(
"path" to v(consumer("/api/12"), producer(regex("^/api/[0-9]{2}$"))),
"correlationId" to v(consumer("1223456"), producer(execute("isProperCorrelationId(\$it)")))
))
}
}
// end::methodBuilder[]

View File

@@ -0,0 +1,61 @@
/*
* 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.
*/
// tag::class[]
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
import org.springframework.cloud.contract.spec.withQueryParameters
contract {
name = "some name"
description = "Some description"
priority = 8
ignored = true
request {
url = url("/foo") withQueryParameters {
parameter("a", "b")
parameter("b", "c")
}
method = PUT
headers {
header("foo", value(client(regex("bar")), server("bar")))
header("fooReq", "baz")
}
body = body(mapOf("foo" to "bar"))
bodyMatchers {
jsonPath("$.foo", byRegex("bar"))
}
}
response {
delay = fixedMilliseconds(1000)
status = OK
headers {
header("foo2", value(server(regex("bar")), client("bar")))
header("foo3", value(server(execute("andMeToo(\$it)")), client("foo33")))
header("fooRes", "baz")
}
body = body(mapOf(
"foo" to "bar",
"foo3" to "baz",
"nullValue" to null
))
bodyMatchers {
jsonPath("$.foo2", byRegex("bar"))
jsonPath("$.foo3", byCommand("executeMe(\$it)"))
jsonPath("$.nullValue", byNull)
}
}
}
// end::class[]

View File

@@ -0,0 +1,60 @@
/*
* 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 contracts
// tag::class[]
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
contract {
request {
method = GET
urlPath = path("/get")
headers {
contentType = APPLICATION_XML
}
}
response {
status = OK
headers {
contentType =APPLICATION_XML
}
body = body("<test>\n" + "<duck type='xtype'>123</duck>\n"
+ "<alpha>abc</alpha>\n" + "<list>\n" + "<elem>abc</elem>\n"
+ "<elem>def</elem>\n" + "<elem>ghi</elem>\n" + "</list>\n"
+ "<number>123</number>\n" + "<aBoolean>true</aBoolean>\n"
+ "<date>2017-01-01</date>\n"
+ "<dateTime>2017-01-01T01:23:45</dateTime>\n"
+ "<time>01:02:34</time>\n"
+ "<valueWithoutAMatcher>foo</valueWithoutAMatcher>\n"
+ "<key><complex>foo</complex></key>\n" + "</test>")
bodyMatchers {
xPath("/test/duck/text()", byRegex("[0-9]{3}"))
xPath("/test/duck/text()", byCommand("equals(\$it)"))
xPath("/test/duck/xxx", byNull)
xPath("/test/duck/text()", byEquality)
xPath("/test/alpha/text()", byRegex(onlyAlphaUnicode))
xPath("/test/alpha/text()", byEquality)
xPath("/test/number/text()", byRegex(number))
xPath("/test/date/text()", byDate)
xPath("/test/dateTime/text()", byTimestamp)
xPath("/test/time/text()", byTime)
xPath("/test/*/complex/text()", byEquality)
xPath("/test/duck/@type", byEquality)
}
}
}
// end::class[]

View File

@@ -0,0 +1,48 @@
/*
* 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 contracts
// tag::class[]
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
contract {
request {
method = PUT
url = url("/multipart")
multipart {
field("formParameter", value(consumer(regex("\".+\"")), producer("\"formParameterValue\"")))
field("someBooleanParameter", value(consumer(anyBoolean), producer("true")))
field("file",
named(
// name of the file
value(consumer(regex(nonEmpty)), producer("filename.csv")),
// content of the file
value(consumer(regex(nonEmpty)), producer("file content")),
// content type for the part
value(consumer(regex(nonEmpty)), producer("application/json"))
)
)
}
headers {
contentType = "multipart/form-data;boundary=AaB03x"
}
}
response {
status = OK
}
}
// end::class[]

View File

@@ -0,0 +1,37 @@
/*
* 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.
*/
// tag::class[]
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract
contract {
request {
url = url("/1")
method = PUT
headers {
contentType = APPLICATION_JSON
}
body = bodyFromFile("request.json")
}
response {
status = OK
body = bodyFromFile("response.json")
headers {
contentType = APPLICATION_JSON
}
}
}
// end::class[]

View File

@@ -0,0 +1,3 @@
{
"status": "REQUEST"
}

View File

@@ -0,0 +1,3 @@
{
"status": "RESPONSE"
}