Merge branch '1.2.x'

This commit is contained in:
Marcin Grzejszczak
2018-01-19 01:18:33 +01:00
123 changed files with 5579 additions and 407 deletions

View File

@@ -1,33 +1,36 @@
== Contract DSL
IMPORTANT: Remember that, inside the contract file, you have to provide the fully
Spring Cloud Contract supports out of the box 2 types of DSL. One written in
`Groovy` and one written in `YAML`.
If you decide to write the contract in Groovy, do not be alarmed if you have not used Groovy
before. Knowledge of the language is not really needed, as the Contract DSL uses only a
tiny subset of it (only literals, method calls and closures). Also, the DSL is statically
typed, to make it programmer-readable without any knowledge of the DSL itself.
IMPORTANT: Remember that, inside the Groovy contract file, you have to provide the fully
qualified name to the `Contract` class and `make` static imports, such as
`org.springframework.cloud.spec.Contract.make { ... }`. You can also provide an import to
the `Contract` class: `import org.springframework.cloud.spec.Contract` and then call
`Contract.make { ... }`.
Contract DSL is written in Groovy, but do not be alarmed if you have not used Groovy
before. Knowledge of the language is not really needed, as the Contract DSL uses only a
tiny subset of it (only literals, method calls and closures). Also, the DSL is statically
typed, to make it programmer-readable without any knowledge of the DSL itself.
TIP: Spring Cloud Contract supports defining multiple contracts in a single file.
The Contract is present in the `spring-cloud-contract-spec` module of the
https://github.com/spring-cloud/spring-cloud-contract/tree/master/spring-cloud-contract-verifier[Spring
Cloud Contract Verifier repository].
The following is a complete example of a contract definition:
The following is a complete example of a Groovy contract definition:
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy[tags=dsl_example,indent=0]
----
NOTE: The preceding example does not contain all the features of the DSL appear. The
remainder of this section describes the other features.
The following is a complete example of a YAML contract definition:
You can compile Contracts to WireMock stubs mapping using standalone maven command:
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_rest.yml[indent=0]
----
TIP: You can compile contracts to stubs mapping using standalone maven command:
`mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:convert`
=== Limitations
@@ -41,7 +44,7 @@ to turn it on, please set the value of the following system property to `true`:
You can also provide the `assertJsonSize` property in the plugin configuration.
WARNING: Because JSON structure can have any form, it can be impossible to parse it
properly when using the `value(consumer(...), producer(...))` notation in `GString`. That
properly when using the Groovy DSL and the `value(consumer(...), producer(...))` notation in `GString`. That
is why you should use the Groovy Map notation.
=== Common Top-Level elements
@@ -60,11 +63,18 @@ The following sections describe the most common top-level elements:
You can add a `description` to your contract. The description is arbitrary text. The
following code shows an example:
.Groovy DSL
[source,groovy,indent=0]
----
include::{contract_spec_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=description,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_rest.yml[indent=0]
----
[[contract-dsl-name]]
==== Name
@@ -78,17 +88,36 @@ generated test not compile. Also, remember that, if you provide the same name fo
multiple contracts, your autogenerated tests fail to compile and your generated stubs
override each other.
.Groovy DSL
[source,groovy,indent=0]
----
include::{contract_spec_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=name,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=name,indent=0]
----
[[contract-dsl-ignoring-contracts]]
==== Ignoring Contracts
If you want to ignore a contract, you can either set a value of ignored contracts in the
plugin configuration or set the `ignored` property on the contract itself:
.Groovy DSL
[source,groovy,indent=0]
----
include::{contract_spec_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=ignored,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=ignored,indent=0]
----
[[contract-dsl-passing-values-from-files]]
==== Passing Values from Files
@@ -108,11 +137,18 @@ following resources in our project.
Further assume that your contract is as follows:
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/resources/classpath/readFromFile.groovy[indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_from_file.yml[indent=0]
----
Further assume that the JSON files is as follows:
*request.json*
@@ -128,9 +164,8 @@ include::{verifier_core_path}/src/test/resources/classpath/response.json[indent=
----
When test or stub generation takes place, the contents of the file is passed to the body
of a request or a response. That works because of the `file(...)` method. The argument of
that method needs to be a file with location relative to the folder in which the contract
lays.
of a request or a response. The name of the file needs to be a file with location
relative to the folder in which the contract lays.
[[contract-dsl-http-top-level-elements]]
==== HTTP Top-Level Elements
@@ -138,62 +173,124 @@ lays.
The following methods can be called in the top-level closure of a contract definition.
`request` and `response` are mandatory. `priority` is optional.
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=http_dsl,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=priority,indent=0]
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0]
...
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=response,indent=0]
...
----
IMPORTANT: If you want to make your contract have a **higher** value of priority
you need to pass a **lower** number to the `priority` tag / method. E.g. `priority` with
value `5` has **higher** priority than `priority` with value `10`.
=== Request
The HTTP protocol requires only **method and address** to be specified in a request. The
The HTTP protocol requires only **method and url** to be specified in a request. The
same information is mandatory in request definition of the Contract.
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=request,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request_obligatory,indent=0]
----
It is possible to specify an absolute rather than relative `url`, but using `urlPath` is
the recommended way, as doing so makes the tests **host-independent**.
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=url,indent=0]
----
`request` may contain **query parameters**, which are specified in a closure nested in a
call to `urlPath` or `url`.
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_rest_with_path.yml[tags=url_path,indent=0]
----
`request` may contain **query parameters**.
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=urlpath,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0]
...
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=query_params,indent=0]
----
`request` may contain additional **request headers**, as shown in the following example:
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=headers,indent=0]
----
`request` may contain a **request body**, as shown in the following example:
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0]
...
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=headers,indent=0]
----
`request` may contain a **request body**:
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=body,indent=0]
----
`request` may contain **multipart** elements. To include multipart elements, call the
`multipart()` method, as shown in the following example
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0]
...
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=body,indent=0]
----
`request` may contain **multipart** elements. To include multipart elements, use the
`multipart` method/section, as shown in the following examples
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy[tags=multipartdsl,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_multipart.yml[indent=0]
----
In the preceding example, we define parameters in either of two ways:
.Groovy DSL
* Directly, by using the map notation, where the value can be a dynamic property (such as
`formParameter: $(consumer(...), producer(...))`).
* By using the `named(...)` method that lets you set a named parameter. A named parameter
@@ -201,6 +298,20 @@ can set a `name` and `content`. You can call it either via a method with two ar
such as `named("fileName", "fileContent")`, or via a map notation, such as
`named(name: "fileName", content: "fileContent")`.
.YAML
* The multipart parameters are set via `multipart.params` section
* The named parameters (the `fileName` and `fileContent` for a given parameter name)
can be set via the `multipart.named` section. That section contains
the `paramName` (name of the parameter), `fileName` (name of the file),
`fileContent` (content of the file) fields
* The dynamic bits can be set via the `matchers.multipart` section
** for parameters use the `params` section that can accept
`regex` or a `predefined` regular expression
** for named params use the `named` section where first you
define the parameter name via `paramName` and then you can pass the
parametrization of either `fileName` or `fileContent` via
`regex` or a `predefined` regular expression
From this contract, the generated test is as follows:
[source,java,indent=0]
@@ -227,17 +338,26 @@ The WireMock stub is as follows:
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy[tags=multipartwiremock,indent=0]
----
=== Response
The response must contain an **HTTP status code** and may contain other information. The
following code shows an example:
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=response,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=response,indent=0]
...
include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=response_obligatory,indent=0]
----
Besides status, the response may contain **headers** and a **body**, both of which are
specified the same way as in the request (see the previous paragraph).
@@ -245,12 +365,19 @@ specified the same way as in the request (see the previous paragraph).
The contract can contain some dynamic properties: timestamps, IDs, and so on. You do not
want to force the consumers to stub their clocks to always return the same value of time
so that it gets matched by the stub. You can provide the dynamic parts in your contracts
so that it gets matched by the stub.
For Groovy DSL you can provide the dynamic parts in your contracts
in two ways: pass them directly in the body or set them in separate sections called
`testMatchers` and `stubMatchers`.
For YAML you can only use the `matchers` section.
==== Dynamic properties inside the body
IMPORTANT: This section is valid only for Groovy DSL. Check out the
<<contract-matchers>> section for YAML examples of a similar feature.
You can set the properties inside the body either with the `value` method or, if you use
the Groovy map notation, with `$()`. The following example shows how to set dynamic
properties with the value method:
@@ -278,6 +405,9 @@ method. Subsequent sections take a closer look at what you can do with those val
==== Regular expressions
IMPORTANT: This section is valid only for Groovy DSL. Check out the
<<contract-matchers>> section for YAML examples of a similar feature.
You can use regular expressions to write your requests in Contract DSL. Doing so is
particularly useful when you want to indicate that a given response should be provided
for requests that follow a given pattern. Also, you can use regular expressions when you
@@ -319,6 +449,9 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
==== Passing Optional Parameters
IMPORTANT: This section is valid only for Groovy DSL. Check out the
<<contract-matchers>> section for YAML examples of a similar feature.
It is possible to provide optional parameters in your contract. However, you can provide
optional parameters only for the following:
@@ -351,6 +484,9 @@ include::{plugins_path}/spring-cloud-contract-converters/src/test/groovy/org/spr
==== Executing Custom Methods on the Server Side
IMPORTANT: This section is valid only for Groovy DSL. Check out the
<<contract-matchers>> section for YAML examples of a similar feature.
You can define a method call that executes on the server side during the test. Such a
method can be added to the class defined as "baseClassForTests" in the configuration. The
following code shows an example of the contract portion of the test case:
@@ -414,7 +550,9 @@ It should resemble the following code:
==== Referencing the Request from the Response
The best situation is to provide fixed values, but sometimes you need to reference a
request in your response. To do so, you can use the `fromRequest()` method, which lets
request in your response.
If you're writing contracts using Groovy DSL, you can use the `fromRequest()` method, which lets
you reference a bunch of elements from the HTTP request. You can use the following
options:
@@ -430,13 +568,36 @@ given name.
* `fromRequest().body(String jsonPath)`: Returns the element from the request that
matches the JSON Path.
If you're using the YAML contract definition you have to use the
http://handlebarsjs.com/[Handlebars] `{{{ }}}` notation with custom, Spring Cloud Contract
functions to achieve this.
* `{{{ request.url }}}`: Returns the request URL and query parameters.
* `{{{ request.query.key.[index] }}}`: Returns the nth query parameter with a given name.
E.g. for key `foo`, first entry `{{{ request.query.foo.[0] }}}`
* `{{{ request.path }}}`: Returns the full path.
* `{{{ request.path.[index] }}}`: Returns the nth path element. E.g.
for first entry ```{{{ request.path.[0] }}}
* `{{{ request.headers.key }}}`: Returns the first header with a given name.
* `{{{ request.headers.key.[index] }}}`: Returns the nth header with a given name.
* `{{{ request.body }}}`: Returns the full request body.
* `{{{ jsonpath this 'your.json.path' }}}`: Returns the element from the request that
matches the JSON Path. E.g. for json path `$.foo` - `{{{ jsonpath this '$.foo' }}}`
Consider the following contract:
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy[tags=template_contract,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_reference_request.yml[indent=0]
----
Running a JUnit test generation leads to a test that resembles the following example:
[source,java,indent=0]
@@ -561,6 +722,7 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
IMPORTANT: Remember to override the `applyGlobally()` method and set it to `false` if you
want the transformation to be applied only for a mapping that explicitly requires it.
[[contract-matchers]]
==== Dynamic Properties in the Matchers Sections
If you work with https://docs.pact.io/[Pact], the following discussion may seem familiar.
@@ -577,6 +739,8 @@ contract.
Currently, Spring Cloud Contract Verifier supports only JSON Path-based matchers with the
following matching possibilities:
.Groovy DSL
* For `stubMatchers`:
** `byEquality()`: The value taken from the response via the provided JSON Path must be
equal to the value provided in the contract.
@@ -615,13 +779,63 @@ following, depending on the JSON path:
*** `Number`: If you point to `Integer`, `Double`, or other kind of number.
*** `Boolean`: If you point to a `Boolean`.
.YAML
_Please read the Groovy section for detailed explanation of
what the types mean_
For YAML the structure of a matcher looks like this
[source,yml,indent=0]
----
- path: $.foo
type: by_regex
value: bar
----
Or if you want to use one of the predefined regular expressions
`[only_alpha_unicode, number, any_boolean, ip_address, hostname,
email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_empty, non_blank]`:
[source,yml,indent=0]
----
- path: $.foo
type: by_regex
predefined: only_alpha_unicode
----
Below you can find the allowed list of `type`s.
* For `stubMatchers`:
** `by_equality`
** `by_regex`
** `by_date`
** `by_timestamp`
** `by_time`
* For `testMatchers`:
** `by_equality`
** `by_regex`
** `by_date`
** `by_timestamp`
** `by_time`
** `by_type`
*** there are 2 additional fields accepted: `minOccurrence` and `maxOccurrence`.
** `by_command`
Consider the following example:
.Groovy DSL
[source,groovy,indent=0]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy[tags=matchers,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_matchers.yml[indent=0]
----
In the preceding example, you can see the dynamic portions of the contract in the
`matchers` sections. For the request part, you can see that, for all fields but
`valueWithoutAMatcher`, the values of the regular expressions that the stub should
@@ -784,6 +998,7 @@ If you're using asynchronous communication on the server side (your controllers
returning `Callable`, `DeferredResult`, and so on), then, inside your contract, you must
provide a `sync()` method in the `response` section. The following code shows an example:
.Groovy DSL
[source,groovy,indent=0]
----
org.springframework.cloud.contract.spec.Contract.make {
@@ -799,6 +1014,13 @@ org.springframework.cloud.contract.spec.Contract.make {
}
----
.YAML
[source,yml,indent=0]
----
response:
async: true
----
=== Working with Context Paths
Spring Cloud Contract supports context paths.
@@ -871,11 +1093,18 @@ following sections explain the differences:
The output message can be triggered by calling a method (such as a `Scheduler` when a was
started and a message was sent), as shown in the following example:
.Groovy DSL
[source,groovy]
----
include::{tests_path}/samples-messaging-integration/src/test/groovy/com/example/IntegrationMessagingApplicationSpec.groovy[tags=method_trigger,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_message_method.yml[indent=0]
----
In the previous example case, the output message is sent to `output` if a method called
`bookReturnedTriggered` is executed. On the message *publisher's* side, we generate a
test that calls that method to trigger the message. On the *consumer* side, you can use
@@ -887,11 +1116,18 @@ the `some_label` to trigger the message.
The output message can be triggered by receiving a message, as shown in the following
example:
.Groovy DSL
[source,groovy]
----
include::{tests_path}/samples-messaging-integration/src/test/groovy/com/example/IntegrationMessagingApplicationSpec.groovy[tags=message_trigger,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_message_input_message.yml[indent=0]
----
In the preceding example, the output message is sent to `output` if a proper message is
received on the `input` destination. On the message *publisher's* side, the engine
generates a test that sends the input message to the defined destination. On the
@@ -901,6 +1137,8 @@ generates a test that sends the input message to the defined destination. On the
[[contract-dsl-consumer-producer]]
==== Consumer/Producer
IMPORTANT: This section is valid only for Groovy DSL.
In HTTP, you have a notion of `client`/`stub and `server`/`test` notation. You can also
use those paradigms in messaging. In addition, Spring Cloud Contract Verifier also
provides the `consumer` and `producer` methods, as presented in the following example
@@ -915,21 +1153,28 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
[[contract-dsl-common]]
==== Common
In the `input {}` or `outputMessage {}` section you can call `assertThat` with the name
In the `input` or `outputMessage` section you can call `assertThat` with the name
of a `method` (e.g. `assertThatMessageIsOnTheQueue()`) that you have defined in the
base class or in a static import. Spring Cloud Pipelines will execute that method
in the genertaed test.
base class or in a static import. Spring Cloud Contract will execute that method
in the generated test.
=== Multiple Contracts in One File
You can define multiple contracts in one file. Such a contract might resemble the
following example:
.Groovy DSL
[source,groovy,indent=0]
----
include::{plugins_path}/spring-cloud-contract-maven-plugin/src/test/projects/multiple-contracts/src/test/resources/contracts/com/hello/v1/WithList.groovy[lines=18..-1,indent=0]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/multiple_contracts.yml[indent=0]
----
In the preceding example, one contract has the `name` field and the other does not. This
leads to generation of two tests that look more or less like this:
@@ -1001,6 +1246,8 @@ your tests far more meaningful.
== Customization
IMPORTANT: This section is valid only for Groovy DSL
You can customize the Spring Cloud Contract Verifier by extending the DSL, as shown in
the remainder of this section.
@@ -1102,13 +1349,6 @@ can generate stubs for other HTTP server implementations).
=== Custom Contract Converter
Assume that your contract is written in a YAML file as follows:
[source,yml]
----
include::{verifier_core_path}/src/test/resources/contract.yml[indent=0]
----
The `ContractConverter` interface lets you register your own implementation of a contract
structure converter. The following code listing shows the `ContractConverter` interface:
@@ -1128,15 +1368,8 @@ The following example shows a typical `spring.factories` file:
[source]
----
include::{verifier_core_path}/src/test/resources/META-INF/spring.factories[indent=0]
----
The following example shows a typical YAML implementation that matches the preceding
example:
[source,groovy]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy[indent=0,lines=16..-1]
org.springframework.cloud.contract.spec.ContractConverter=\
org.springframework.cloud.contract.verifier.converter.YamlContractConverter
----
==== Pact Converter

View File

@@ -15,6 +15,10 @@ Spring Cloud Contract Verifier stand out on the "market" of Consumer Driven Cont
- Stub Runner functionality - the stubs are automatically downloaded at runtime from Nexus / Artifactory
- Spring Cloud integration - no discovery service is needed for integration tests
=== I don't want to write a contract in Groovy!
No problem. You can write a contract in YAML!
=== What is this value(consumer(), producer()) ?
One of the biggest challenges related to stubs is their reusability. Only if they can be vastly used, will they serve their purpose.
@@ -370,4 +374,5 @@ for this for WireMock. In case of other HTTP server stubs you'll have to impleme
==== Can I reference text from file?
Yes! With version 1.2.0 we've added such a possibility. It's enough to call `file(...)` method in the
DSL and provide a path relative to where the contract lays.
DSL and provide a path relative to where the contract lays.
If you're using YAML just use the `bodyFromFile` property.

View File

@@ -106,11 +106,18 @@ Assume that you want to send a request containing the ID of a client company and
amount it wants to borrow from us. You also want to send it to the /fraudcheck url via
the PUT method.
.Groovy DSL
[source,groovy,indent=0]
----
include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[]
----
.YAML
[source,yml,indent=0]
----
include::{introduction_url}/samples/standalone/yml/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.yml[]
----
==== Client Side
Spring Cloud Contract generates stubs, which you can use during client-side testing.
@@ -144,7 +151,7 @@ your application behaves in a different way, especially in production.
To ensure that your application behaves the way you define in your stub, tests are
generated from the stub you provide.
The autogenerated test looks like this:
The autogenerated test looks, more or less, like this:
[source,java,indent=0]
----
@@ -260,7 +267,7 @@ clone it.
[source,bash,indent=0]
----
git clone https://your-git-server.com/server-side.git local-http-server-repo
$ git clone https://your-git-server.com/server-side.git local-http-server-repo
----
*Define the contract locally in the repo of Fraud Detection service.*
@@ -271,13 +278,21 @@ your expectations. To do so, write the following contract:
IMPORTANT: Place the contract under `src/test/resources/contracts/fraud` folder. The `fraud` folder
is important because the producer's test base class name references that folder.
.Groovy DSL
[source,groovy,indent=0]
----
include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[]
----
The Contract is written using a statically typed Groovy DSL. You might wonder what about
those `value(client(...), server(...))` parts. By using this notation, Spring Cloud
.YAML
[source,yml,indent=0]
----
include::{introduction_url}/samples/standalone/yml/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.yml[]
----
The YML contract is quite straight-forward. However when you take a look at the Contract
written using a statically typed Groovy DSL - you might wonder what the
`value(client(...), server(...))` parts are. By using this notation, Spring Cloud
Contract lets you define parts of a JSON block, a URL, etc., which are dynamic. In case
of an identifier or a timestamp, you need not hardcode a value. You want to allow some
different ranges of values. To enable ranges of values, you can set regular expressions
@@ -333,8 +348,8 @@ stubs. You need to skip the test generation and execution. When you execute:
[source,bash,indent=0]
----
cd local-http-server-repo
./mvnw clean install -DskipTests
$ cd local-http-server-repo
$ ./mvnw clean install -DskipTests
----
In the logs, you see something like this:
@@ -440,8 +455,8 @@ include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com
[source,bash,indent=0]
----
git checkout -b contract-change-pr master
git pull https://your-git-server.com/server-side-fork.git contract-change-pr
$ git checkout -b contract-change-pr master
$ git pull https://your-git-server.com/server-side-fork.git contract-change-pr
----
You must add the dependencies needed by the autogenerated tests:
@@ -511,8 +526,9 @@ public void validate_shouldMarkClientAsFraud() throws Exception {
}
----
As you can see, all the `producer()` parts of the Contract that were present in the
If you used the Groovy DSL, you can see, all the `producer()` parts of the Contract that were present in the
`value(consumer(...), producer(...))` blocks got injected into the test.
In case of using YAML, the same applied for the `matchers` sections of the `response`.
Note that, on the producer side, you are also doing TDD. The expectations are expressed
in the form of a test. This test sends a request to our own application with the URL,
@@ -543,9 +559,9 @@ Once you finish your work, you can deploy your change. First, merge the branch:
[source,bash,indent=0]
----
git checkout master
git merge --no-ff contract-change-pr
git push origin master
$ git checkout master
$ git merge --no-ff contract-change-pr
$ git push origin master
----
Your CI might run something like `./mvnw clean deploy`, which would publish both the
@@ -559,8 +575,8 @@ As a developer of the Loan Issuance service (a consumer of the Fraud Detection s
[source,bash,indent=0]
----
git checkout master
git merge --no-ff contract-change-pr
$ git checkout master
$ git merge --no-ff contract-change-pr
----
*Work online.*

View File

@@ -89,11 +89,18 @@ it is resolved as a channel name. For *Camel*, that's a certain component (for e
Here is an example for Camel. For the given contract:
.Groovy DSL
[source,groovy]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_method_dsl]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_message_scenario1.yml[indent=0]
----
The following JUnit test is created:
[source,groovy]
@@ -112,11 +119,18 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
Here is an example for Camel. For the given contract:
.Groovy DSL
[source,groovy]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_message_dsl]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_message_scenario2.yml[indent=0]
----
The following JUnit test is created:
[source,groovy]
@@ -135,11 +149,18 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
Here is an example for Camel. For the given contract:
.Groovy DSL
[source,groovy]
----
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_no_output_dsl]
----
.YAML
[source,yml,indent=0]
----
include::{verifier_core_path}/src/test/resources/yml/contract_message_scenario3.yml[indent=0]
----
The following JUnit test is created:
[source,groovy]

View File

@@ -875,7 +875,8 @@ exclude the unwanted dependencies.
You can handle scenarios with Spring Cloud Contract Verifier. All you need to do is to
stick to the proper naming convention while creating your contracts. The convention
requires including an order number followed by an underscore, as shown in this example:
requires including an order number followed by an underscore. This will work regardles
of whether you're working with YAML or Groovy. Example:
[source,indent=0]
----