Updated docs
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
@@ -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[]
|
||||
@@ -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[]
|
||||
@@ -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[]
|
||||
@@ -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[]
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"status": "REQUEST"
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"status": "RESPONSE"
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user