Skip to content

Commit

Permalink
Added standalone samples
Browse files Browse the repository at this point in the history
  • Loading branch information
marcingrzejszczak committed Sep 26, 2024
1 parent 99ca103 commit a061f16
Show file tree
Hide file tree
Showing 233 changed files with 14,493 additions and 10 deletions.
28 changes: 18 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<!-- standalone -->
<module>standalone/contracts</module>
<module>standalone/dsl/http-server</module>
<module>standalone/dsl/http-client</module>
<module>standalone/restdocs/http-server</module>
<module>standalone/restdocs/http-client</module>
<module>standalone/webclient/http-server</module>
<module>standalone/webclient/http-client</module>

<module>common</module>
<module>wiremock</module>
<module>wiremock-for-contract-docs</module>
Expand Down Expand Up @@ -93,6 +102,15 @@
<activeByDefault>false</activeByDefault>
</activation>
<modules>
<!-- standalone -->
<module>standalone/contracts</module>
<module>standalone/dsl/http-server</module>
<module>standalone/dsl/http-client</module>
<module>standalone/restdocs/http-server</module>
<module>standalone/restdocs/http-client</module>
<module>standalone/webclient/http-server</module>
<module>standalone/webclient/http-client</module>

<module>beer_contracts</module>
<module>wiremock</module>
<module>wiremock-for-contract-docs</module>
Expand Down Expand Up @@ -149,16 +167,6 @@
<module>consumer_kotlin</module>
</modules>
</profile>
<profile>
<id>highmem</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<modules>
<module>producer_java</module>
<module>consumer_java</module>
</modules>
</profile>
</profiles>

</project>
9 changes: 9 additions & 0 deletions scripts/runGradleBuilds.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ function build_gradle() {
if [[ "${BUILD_COMMON}" == "true" ]]; then
build common
fi
# Standalone
build standalone/contracts
build standalone/dsl/http-server
build standalone/dsl/http-client
build standalone/restdocs/http-server
build standalone/restdocs/http-client
build standalone/webclient/http-server
build standalone/webclient/http-client

build producer
build producer_testng
# build producer_jaxrs
Expand Down
Binary file not shown.
1 change: 1 addition & 0 deletions standalone/contracts/.mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
68 changes: 68 additions & 0 deletions standalone/contracts/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
= Common contracts repo

This repo contains all contracts for apps in the system.

== As a consumer

You are working offline in order to play around with the API of the producer.
What you need to do is to have the producer's stubs installed locally. To do that
you have to (from the root of the repo)

[source,bash]
----
cd com/example/server/
mvn clean install -DskipTests
----

Then if you do `ls ./target` you'll see `server-0.0.1-SNAPSHOT-stubs.jar`. This jar will
contain the stubs generated from your contracts. That way you
can reference the `com.example:server:+:stubs` dependency in your consumer tests.

== As a producer

Assuming that the consumers have filed a PR with the proposed contract the producers
can work offline to generate tests and stubs. To work offline, as a producer you just have
to go to the root folder of the contracts and:

[source,bash]
----
./mvnw clean install -DskipTests
----

Then if you do `ls ./target` you'll see `contracts-0.0.1-SNAPSHOT.jar`. This file contains
all DSL contracts, for all applications.

Now the producer can include the `contracts-0.0.1-SNAPSHOT.jar` from your local maven repository.
You can achieve that by setting the proper flag in plugin properties.

Example for Maven

[source,xml]
----
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<contractsMode>LOCAL</contractsMode>
<contractDependency>
<groupId>com.example.standalone</groupId>
<artifactId>contracts</artifactId>
</contractDependency>
</configuration>
</plugin>
----

and for Gradle:

[source,groovy]
----
contracts {
testFramework ='Spock'
testMode = 'JaxRsClient'
baseClassForTests = 'org.springframework.cloud.MvcSpec'
stubsMode = 'LOCAL'
contractDependency {
stringNotation = "com.example:contracts"
}
}
----
82 changes: 82 additions & 0 deletions standalone/contracts/com/example/server/client1/expectation.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2013-2020 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

org.springframework.cloud.contract.spec.Contract.make {
request { // (1)
method 'PUT' // (2)
url '/fraudcheck' // (3)
body([ // (4)
clientId : $(regex('[0-9]{10}')),
loanAmount: 99999
])
headers { // (5)
contentType('application/vnd.fraud.v1+json')
}
}
response { // (6)
status OK() // (7)
body([ // (8)
fraudCheckStatus: "FRAUD",
rejectionReason : "Amount too high"
])
headers { // (9)
contentType('application/vnd.fraud.v1+json')
}
}
}

/*
Since we don't want to force on the user to hardcode values of fields that are dynamic
(timestamps, database ids etc.), one can parametrize those entries. If you wrap your field's
value in a `$(...)` or `value(...)` and provide a dynamic value of a field then
the concrete value will be generated for you. If you want to be really explicit about
which side gets which value you can do that by using the `value(consumer(...), producer(...))` notation.
That way what's present in the `consumer` section will end up in the produced stub. What's
there in the `producer` will end up in the autogenerated test. If you provide only the
regular expression side without the concrete value then Spring Cloud Contract will generate one for you.
From the Consumer perspective, when shooting a request in the integration test:
(1) - If the consumer sends a request
(2) - With the "PUT" method
(3) - to the URL "/fraudcheck"
(4) - with the JSON body that
* has a field `clientId` that matches a regular expression `[0-9]{10}`
* has a field `loanAmount` that is equal to `99999`
(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
(6) - then the response will be sent with
(7) - status equal `200`
(8) - and JSON body equal to
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
(9) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
From the Producer perspective, in the autogenerated producer-side test:
(1) - A request will be sent to the producer
(2) - With the "PUT" method
(3) - to the URL "/fraudcheck"
(4) - with the JSON body that
* has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}`
* has a field `loanAmount` that is equal to `99999`
(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
(6) - then the test will assert if the response has been sent with
(7) - status equal `200`
(8) - and JSON body equal to
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
(9) - with header `Content-Type` matching `application/vnd.fraud.v1+json.*`
*/
83 changes: 83 additions & 0 deletions standalone/contracts/com/example/server/client2/expectation.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2013-2020 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

org.springframework.cloud.contract.spec.Contract.make {
request { // (1)
method 'PUT' // (2)
url '/fraudcheck2' // (3)
body([ // (4)
clientId : value(consumer(regex('[0-9]{10}'))),
loanAmount: 99999
])
headers { // (5)
header('Content-Type', 'application/vnd.fraud.v1+json')
}
}
response { // (6)
status OK() // (7)
body([ // (8)
fraudCheckStatus: "FRAUD",
rejectionReason : "Amount too high"
])
headers { // (9)
header('Content-Type': value(
producer(regex('application/vnd.fraud.v1.json.*')),
consumer('application/vnd.fraud.v1+json'))
)
}
}
}

/*
Since we don't want to force on the user to hardcode values of fields that are dynamic
(timestamps, database ids etc.), one can provide parametrize those entries by using the
`value(consumer(...), producer(...))` method. That way what's present in the `consumer`
section will end up in the produced stub. What's there in the `producer` will end up in the
autogenerated test. If you provide only the regular expression side without the concrete
value then Spring Cloud Contract will generate one for you.
From the Consumer perspective, when shooting a request in the integration test:
(1) - If the consumer sends a request
(2) - With the "PUT" method
(3) - to the URL "/fraudcheck"
(4) - with the JSON body that
* has a field `clientId` that matches a regular expression `[0-9]{10}`
* has a field `loanAmount` that is equal to `99999`
(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
(6) - then the response will be sent with
(7) - status equal `200`
(8) - and JSON body equal to
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
(9) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
From the Producer perspective, in the autogenerated producer-side test:
(1) - A request will be sent to the producer
(2) - With the "PUT" method
(3) - to the URL "/fraudcheck"
(4) - with the JSON body that
* has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}`
* has a field `loanAmount` that is equal to `99999`
(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
(6) - then the test will assert if the response has been sent with
(7) - status equal `200`
(8) - and JSON body equal to
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
(9) - with header `Content-Type` matching `application/vnd.fraud.v1+json.*`
*/
83 changes: 83 additions & 0 deletions standalone/contracts/com/example/server/client3/expectation.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2013-2020 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

org.springframework.cloud.contract.spec.Contract.make {
request { // (1)
method 'PUT' // (2)
url '/fraudcheck3' // (3)
body([ // (4)
clientId : value(consumer(regex('[0-9]{10}'))),
loanAmount: 99999
])
headers { // (5)
header('Content-Type', 'application/vnd.fraud.v1+json')
}
}
response { // (6)
status OK() // (7)
body([ // (8)
fraudCheckStatus: "FRAUD",
rejectionReason : "Amount too high"
])
headers { // (9)
header('Content-Type': value(
producer(regex('application/vnd.fraud.v1.json.*')),
consumer('application/vnd.fraud.v1+json'))
)
}
}
}

/*
Since we don't want to force on the user to hardcode values of fields that are dynamic
(timestamps, database ids etc.), one can provide parametrize those entries by using the
`value(consumer(...), producer(...))` method. That way what's present in the `consumer`
section will end up in the produced stub. What's there in the `producer` will end up in the
autogenerated test. If you provide only the regular expression side without the concrete
value then Spring Cloud Contract will generate one for you.
From the Consumer perspective, when shooting a request in the integration test:
(1) - If the consumer sends a request
(2) - With the "PUT" method
(3) - to the URL "/fraudcheck"
(4) - with the JSON body that
* has a field `clientId` that matches a regular expression `[0-9]{10}`
* has a field `loanAmount` that is equal to `99999`
(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
(6) - then the response will be sent with
(7) - status equal `200`
(8) - and JSON body equal to
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
(9) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
From the Producer perspective, in the autogenerated producer-side test:
(1) - A request will be sent to the producer
(2) - With the "PUT" method
(3) - to the URL "/fraudcheck"
(4) - with the JSON body that
* has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}`
* has a field `loanAmount` that is equal to `99999`
(5) - with header `Content-Type` equal to `application/vnd.fraud.v1+json`
(6) - then the test will assert if the response has been sent with
(7) - status equal `200`
(8) - and JSON body equal to
{ "fraudCheckStatus": "FRAUD", "rejectionReason": "Amount too high" }
(9) - with header `Content-Type` matching `application/vnd.fraud.v1+json.*`
*/
Loading

0 comments on commit a061f16

Please sign in to comment.