542 lines
23 KiB
Plaintext
542 lines
23 KiB
Plaintext
[[getting-started-cdc]]
|
|
= Step-by-step Guide to Consumer Driven Contracts (CDC) with Contracts on the Producer Side
|
|
|
|
include::partial$_attributes.adoc[]
|
|
|
|
Consider an example of fraud detection and the loan issuance process. The business
|
|
scenario is such that we want to issue loans to people but do not want them to steal from
|
|
us. The current implementation of our system grants loans to everybody.
|
|
|
|
Assume that `Loan Issuance` is a client to the `Fraud Detection` server. In the current
|
|
sprint, we must develop a new feature: if a client wants to borrow too much money,
|
|
we mark the client as a fraud.
|
|
|
|
Technical remarks
|
|
|
|
* Fraud Detection has an `artifact-id` of `http-server`.
|
|
* Loan Issuance has an `artifact-id` of `http-client`.
|
|
* Both have a `group-id` of `com.example`.
|
|
* For the sake of this example, the `Stub Storage` is Nexus/Artifactory.
|
|
|
|
Social remarks
|
|
|
|
* Both the client and the server development teams need to communicate directly and
|
|
discuss changes while going through the process.
|
|
* CDC is all about communication.
|
|
|
|
The server-side code is available under Spring Cloud Contract's repository `samples/standalone/dsl/http-server` path, and the client-side code is available under Spring Cloud Contract's repository `samples/standalone/dsl/http-client` path.
|
|
|
|
TIP: In this case, the producer owns the contracts. Physically, all the contracts are
|
|
in the producer's repository.
|
|
|
|
[[getting-started-cdc-technical-note]]
|
|
== Technical Note
|
|
|
|
If you use the SNAPSHOT, Milestone, or Release Candidate versions, you need to add the
|
|
following section to your build:
|
|
|
|
[tabs]
|
|
======
|
|
Maven::
|
|
+
|
|
[source,xml,indent=0,subs="verbatim",role="primary"]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/pom.xml[tags=repos,indent=0]
|
|
----
|
|
======
|
|
////
|
|
|
|
////
|
|
[source,groovy,indent=0,subs="verbatim",role="secondary"]
|
|
.Gradle
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/build.gradle[tags=deps_repos,indent=0]
|
|
----
|
|
|
|
For simplicity, we use the following acronyms:
|
|
|
|
- Loan Issuance (LI): The HTTP client
|
|
- Fraud Detection (FD): The HTTP server
|
|
- SCC: Spring Cloud Contract
|
|
|
|
[[getting-started-cdc-consumer]]
|
|
== The Consumer Side (Loan Issuance)
|
|
|
|
As a developer of the Loan Issuance service (a consumer of the Fraud Detection server), you might do the following steps:
|
|
|
|
. Start doing TDD by writing a test for your feature.
|
|
. Write the missing implementation.
|
|
. Clone the Fraud Detection service repository locally.
|
|
. Define the contract locally in the repository of the fraud detection service.
|
|
. Add the Spring Cloud Contract (SCC) plugin.
|
|
. Run the integration tests.
|
|
. File a pull request.
|
|
. Create an initial implementation.
|
|
. Take over the pull request.
|
|
. Write the missing implementation.
|
|
. Deploy your application.
|
|
. Work online.
|
|
|
|
We start with the loan issuance flow, which the following UML diagram shows:
|
|
|
|
[plantuml, getting-started-cdc-client, png]
|
|
----
|
|
"Loan\nIssuance"->"Loan\nIssuance": start doing TDD\nby writing a test\nfor your feature
|
|
"Loan\nIssuance"->"Loan\nIssuance": write the \nmissing implementation
|
|
"Loan\nIssuance"->"Loan\nIssuance": run a test - it fails\ndue to no server running
|
|
"Loan\nIssuance"->"Fraud\nDetection\nClone": clone the repository
|
|
"Fraud\nDetection\nClone"->"Fraud\nDetection\nClone": add missing dependencies\n& define contracts
|
|
"Fraud\nDetection\nClone"->"Fraud\nDetection\nClone": add the SCC plugin
|
|
"Fraud\nDetection\nClone"->"FD \nClone Build": install the stubs locally
|
|
"FD \nClone Build"->"SCC Plugin \nin FD Clone": generate stubs \nand stubs \nartifact (e.g. stubs-jar)
|
|
"SCC Plugin \nin FD Clone"->"FD \nClone Build": stubs and artifacts\ngenerated
|
|
"FD \nClone Build"->"Local storage": install the stubs locally
|
|
"Local storage"->"FD \nClone Build": stub sucessfully installed
|
|
"FD \nClone Build"->"Fraud\nDetection\nClone": build successful
|
|
"Loan\nIssuance"->"Loan\nIssuance": add a SCC\nStub Runner\ndependency\nand setup
|
|
"Loan\nIssuance"->"LI\nSCC\nStub Runner": start stubs\nof FD from\nlocal storage
|
|
"LI\nSCC\nStub Runner"->"Local storage": find stubs of [FD]
|
|
"Local storage"->"LI\nSCC\nStub Runner": stubs of [FD] found
|
|
"LI\nSCC\nStub Runner"->"FD stub": run stubs of [FD]
|
|
"FD stub"->"LI\nSCC\nStub Runner": [FD] stub is running
|
|
"LI\nSCC\nStub Runner"->"Loan\nIssuance": stubs running and ready for the test
|
|
"Loan\nIssuance"->"Loan\nIssuance": run a test
|
|
"Loan\nIssuance"->"FD stub": the test\nsends a request\nto the running stub
|
|
"FD stub"->"Loan\nIssuance": stub responds successfuly
|
|
"Loan\nIssuance"->"Loan\nIssuance": the test passes successfully
|
|
"Loan\nIssuance"->"Fraud\nDetection": send a pull request\nwith the\nsuggested contracts
|
|
----
|
|
|
|
[[getting-started-cdc-consumer-start]]
|
|
=== Start Doing TDD by Writing a Test for Your Feature
|
|
|
|
The following listing shows a test that we might use to check whether a loan amount is too
|
|
large:
|
|
|
|
[source,groovy,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java[tags=client_tdd,indent=0]
|
|
----
|
|
|
|
Assume that you have written a test of your new feature. If a loan application for a big
|
|
amount is received, the system should reject that loan application with some description.
|
|
|
|
[[getting-started-cdc-consumer-write]]
|
|
=== Write the Missing Implementation
|
|
|
|
At some point in time, you need to send a request to the Fraud Detection service. Assume
|
|
that you need to send the request containing the ID of the client and the amount the
|
|
client wants to borrow. You want to send it to the `/fraudcheck` URL by using the `PUT` method.
|
|
To do so, you might use code similar to the following:
|
|
|
|
[source,groovy,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java[tags=client_call_server,indent=0]
|
|
----
|
|
|
|
For simplicity, the port of the Fraud Detection service is set to `8080`, and the
|
|
application runs on `8090`.
|
|
|
|
NOTE: If you start the test at this point, it breaks, because no service currently runs on port
|
|
`8080`.
|
|
|
|
[[getting-started-cdc-consumer-clone]]
|
|
=== Clone the Fraud Detection service repository locally
|
|
|
|
You can start by playing around with the server side contract. To do so, you must first
|
|
clone it, by running the following command:
|
|
|
|
[source,bash,indent=0]
|
|
----
|
|
$ git clone https://your-git-server.com/server-side.git local-http-server-repo
|
|
----
|
|
|
|
[[getting-started-cdc-consumer-define]]
|
|
=== Define the Contract Locally in the Repository of the Fraud Detection Service
|
|
|
|
As a consumer, you need to define what exactly you want to achieve. You need to formulate
|
|
your expectations. To do so, write the following contract:
|
|
|
|
IMPORTANT: Place the contract in the `src/test/resources/contracts/fraud` folder. The `fraud` folder
|
|
is important because the producer's test base class name references that folder.
|
|
|
|
The following example shows our contract, in both Groovy and YAML:
|
|
|
|
[source,groovy,indent=0,role="primary"]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[]
|
|
----
|
|
|
|
[source,yaml,indent=0,role="secondary"]
|
|
.yaml
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldMarkClientAsFraud.yml[]
|
|
----
|
|
|
|
The YML contract is quite straightforward. However, when you take a look at the contract
|
|
written with 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, or other structure that is dynamic. In the 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
|
|
that match those values for the consumer side. You can provide the body by means of either
|
|
a map notation or a String with interpolations. We highly recommend using the map notation.
|
|
|
|
TIP: To set up contracts, you must understand the map notation. See the
|
|
https://groovy-lang.org/json.html[Groovy docs regarding JSON].
|
|
|
|
The previously shown contract is an agreement between two sides that:
|
|
|
|
* If an HTTP request is sent with all of:
|
|
** A `PUT` method on the `/fraudcheck` endpoint
|
|
** A JSON body with a `client.id` that matches the regular expression `[0-9]\{10}` and
|
|
`loanAmount` equal to `99999`
|
|
** A `Content-Type` header with a value of `application/vnd.fraud.v1+json`
|
|
* Then an HTTP response is sent to the consumer that
|
|
** Has status `200`
|
|
** Contains a JSON body with the `fraudCheckStatus` field containing a value of `FRAUD` and
|
|
the `rejectionReason` field having a value of `Amount too high`
|
|
** Has a `Content-Type` header with a value of `application/vnd.fraud.v1+json`
|
|
|
|
Once you are ready to check the API in practice in the integration tests, you need to
|
|
install the stubs locally.
|
|
|
|
[[getting-started-cdc-consumer-add]]
|
|
=== Add the Spring Cloud Contract Verifier Plugin
|
|
|
|
We can add either a Maven or a Gradle plugin. In this example, we show how to add Maven.
|
|
First, we add the `Spring Cloud Contract` BOM, as the following example shows:
|
|
|
|
[source,xml,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/pom.xml[tags=contract_bom,indent=0]
|
|
----
|
|
|
|
Next, add the `Spring Cloud Contract Verifier` Maven plugin, as the following example shows:
|
|
|
|
[source,xml,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/pom.xml[tags=contract_maven_plugin,indent=0]
|
|
----
|
|
|
|
Since the plugin was added, you get the `Spring Cloud Contract Verifier` features, which,
|
|
from the provided contracts:
|
|
|
|
- Generate and run tests
|
|
- Produce and install stubs
|
|
|
|
You do not want to generate tests, since you, as the consumer, want only to play with the
|
|
stubs. You need to skip the test generation and invokation. To do so, run the following commands:
|
|
|
|
[source,bash,indent=0]
|
|
----
|
|
$ cd local-http-server-repo
|
|
$ ./mvnw clean install -DskipTests
|
|
----
|
|
|
|
Once you run those commands, you should you see something like the following content in the logs:
|
|
|
|
[source,bash,indent=0]
|
|
----
|
|
[INFO] --- spring-cloud-contract-maven-plugin:1.0.0.BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
|
|
[INFO] Building jar: /some/path/http-server/target/http-server-0.0.1-SNAPSHOT-stubs.jar
|
|
[INFO]
|
|
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ http-server ---
|
|
[INFO] Building jar: /some/path/http-server/target/http-server-0.0.1-SNAPSHOT.jar
|
|
[INFO]
|
|
[INFO] --- spring-boot-maven-plugin:1.5.5.BUILD-SNAPSHOT:repackage (default) @ http-server ---
|
|
[INFO]
|
|
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ http-server ---
|
|
[INFO] Installing /some/path/http-server/target/http-server-0.0.1-SNAPSHOT.jar to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT.jar
|
|
[INFO] Installing /some/path/http-server/pom.xml to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT.pom
|
|
[INFO] Installing /some/path/http-server/target/http-server-0.0.1-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar
|
|
----
|
|
|
|
The following line is extremely important:
|
|
|
|
[source,bash,indent=0]
|
|
----
|
|
[INFO] Installing /some/path/http-server/target/http-server-0.0.1-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar
|
|
----
|
|
|
|
It confirms that the stubs of the `http-server` have been installed in the local
|
|
repository.
|
|
|
|
[[getting-started-cdc-consumer-run]]
|
|
=== Running the Integration Tests
|
|
|
|
In order to profit from the Spring Cloud Contract Stub Runner functionality of automatic
|
|
stub downloading, you must do the following in your consumer side project (`Loan
|
|
Application service`):
|
|
|
|
. Add the `Spring Cloud Contract` BOM, as follows:
|
|
+
|
|
[source,xml,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-client/pom.xml[tags=contract_bom,indent=0]
|
|
----
|
|
|
|
. Add the dependency to `Spring Cloud Contract Stub Runner`, as follows:
|
|
+
|
|
[source,xml,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-client/pom.xml[tags=stub_runner,indent=0]
|
|
----
|
|
|
|
. Annotate your test class with `@AutoConfigureStubRunner`. In the annotation, provide the
|
|
`group-id` and `artifact-id` for the Stub Runner to download the stubs of your
|
|
collaborators.
|
|
+
|
|
[source,groovy,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java[tags=autoconfigure_stubrunner,indent=0]
|
|
----
|
|
|
|
. (Optional) Because you are playing with the collaborators offline, you
|
|
can also provide the offline work switch (`StubRunnerProperties.StubsMode.LOCAL`).
|
|
|
|
Now, when you run your tests, you see something like the following output in the logs:
|
|
|
|
[source,bash,indent=0]
|
|
----
|
|
2016-07-19 14:22:25.403 INFO 41050 --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Desired version is + - will try to resolve the latest version
|
|
2016-07-19 14:22:25.438 INFO 41050 --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved version is 0.0.1-SNAPSHOT
|
|
2016-07-19 14:22:25.439 INFO 41050 --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolving artifact com.example:http-server:jar:stubs:0.0.1-SNAPSHOT using remote repositories []
|
|
2016-07-19 14:22:25.451 INFO 41050 --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Resolved artifact com.example:http-server:jar:stubs:0.0.1-SNAPSHOT to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar
|
|
2016-07-19 14:22:25.465 INFO 41050 --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacking stub from JAR [URI: file:/path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar]
|
|
2016-07-19 14:22:25.475 INFO 41050 --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Unpacked file to [/var/folders/0p/xwq47sq106x1_g3dtv6qfm940000gq/T/contracts100276532569594265]
|
|
2016-07-19 14:22:27.737 INFO 41050 --- [ main] o.s.c.c.stubrunner.StubRunnerExecutor : All stubs are now running RunningStubs [namesAndPorts={com.example:http-server:0.0.1-SNAPSHOT:stubs=8080}]
|
|
----
|
|
|
|
This output means that Stub Runner has found your stubs and started a server for your application
|
|
with a group ID of `com.example` and an artifact ID of `http-server` with version `0.0.1-SNAPSHOT` of
|
|
the stubs and with the `stubs` classifier on port `8080`.
|
|
|
|
[[getting-started-cdc-consumer-file]]
|
|
=== Filing a Pull Request
|
|
|
|
What you have done until now is an iterative process. You can play around with the
|
|
contract, install it locally, and work on the consumer side until the contract works as
|
|
you wish.
|
|
|
|
Once you are satisfied with the results and the test passes, you can publish a pull request to
|
|
the server side. Currently, the consumer side work is done.
|
|
|
|
[[getting-started-cdc-producer]]
|
|
== The Producer Side (Fraud Detection server)
|
|
|
|
As a developer of the Fraud Detection server (a server to the Loan Issuance service), you
|
|
might want to:
|
|
|
|
- Take over the pull request
|
|
- Write the missing implementation
|
|
- Deploy the application
|
|
|
|
The following UML diagram shows the fraud detection flow:
|
|
|
|
[plantuml, getting-started-cdc-server, png]
|
|
----
|
|
"Fraud\nDetection"->"Fraud\nDetection": take over the\n pull request
|
|
"Fraud\nDetection"->"Fraud\nDetection": setup\nSpring Cloud\nContract plugin
|
|
"Fraud\nDetection"->"Fraud\nDetection\nBuild": run the build
|
|
"Fraud\nDetection\nBuild"->"SCC Plugin": generate tests\nstubs \nand stubs artifact \n(e.g. stubs-jar)
|
|
"SCC Plugin"->"Fraud\nDetection\nBuild": tests and stubs generated
|
|
"Fraud\nDetection\nBuild"->"Fraud\nDetection\nBuild": run tests
|
|
"Fraud\nDetection\nBuild"->"Fraud\nDetection": generated tests failed!
|
|
"Fraud\nDetection"->"Fraud\nDetection": setup\nbase classes\nfor contract tests
|
|
"Fraud\nDetection"->"Fraud\nDetection\nBuild": run the build
|
|
"Fraud\nDetection\nBuild"->"SCC Plugin": generate tests\nstubs \nand stubs artifact \n(e.g. stubs-jar)
|
|
"SCC Plugin"->"Fraud\nDetection\nBuild": tests and stubs generated
|
|
"Fraud\nDetection\nBuild"->"Fraud\nDetection\nBuild": run tests
|
|
"Fraud\nDetection\nBuild"->"Fraud\nDetection": all the tests passed!
|
|
"Fraud\nDetection"->"Fraud\nDetection": commit and push changes
|
|
"Fraud\nDetection"->"CI": commit pushed!\nTriggers the build
|
|
"CI"->"Stub Storage": build successful,\nupload artifacts
|
|
----
|
|
|
|
[[getting-started-cdc-producer-pr]]
|
|
=== Taking over the Pull Request
|
|
|
|
As a reminder, the following listing shows the initial implementation:
|
|
|
|
[source,java,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=server_api,indent=0]
|
|
include::{samples_path}/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=initial_impl,indent=0]
|
|
}
|
|
----
|
|
|
|
Then you can run the following commands:
|
|
|
|
[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
|
|
----
|
|
|
|
You must add the dependencies needed by the autogenerated tests, as follows:
|
|
|
|
[source,xml,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/pom.xml[tags=verifier_test_dependencies,indent=0]
|
|
----
|
|
|
|
In the configuration of the Maven plugin, you must pass the `packageWithBaseClasses` property, as follows:
|
|
|
|
[source,xml,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/pom.xml[tags=contract_maven_plugin,indent=0]
|
|
----
|
|
|
|
IMPORTANT: This example uses "`convention-based`" naming by setting the
|
|
`packageWithBaseClasses` property. Doing so means that the two last packages combine to
|
|
make the name of the base test class. In our case, the contracts were placed under
|
|
`src/test/resources/contracts/fraud`. Since you do not have two packages starting from
|
|
the `contracts` folder, pick only one, which should be `fraud`. Add the `Base` suffix and
|
|
capitalize `fraud`. That gives you the `FraudBase` test class name.
|
|
|
|
All the generated tests extend that class. Over there, you can set up your Spring Context
|
|
or whatever is necessary. In this case, you should use https://github.com/rest-assured/rest-assured[Rest Assured MVC] to
|
|
start the server side `FraudDetectionController`. The following listing shows the
|
|
`FraudBase` class:
|
|
|
|
[source,java,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudBase.java[]
|
|
----
|
|
|
|
Now, if you run the `./mvnw clean install`, you get something like the following output:
|
|
|
|
[source,bash,indent=0]
|
|
----
|
|
Results :
|
|
|
|
Tests in error:
|
|
ContractVerifierTest.validate_shouldMarkClientAsFraud:32 » IllegalState Parsed...
|
|
----
|
|
|
|
This error occurs because you have a new contract from which a test was generated, and it
|
|
failed since you have not implemented the feature. The auto-generated test would look
|
|
like the following test method:
|
|
|
|
[source,java,indent=0]
|
|
----
|
|
@Test
|
|
public void validate_shouldMarkClientAsFraud() throws Exception {
|
|
// given:
|
|
MockMvcRequestSpecification request = given()
|
|
.header("Content-Type", "application/vnd.fraud.v1+json")
|
|
.body("{\"client.id\":\"1234567890\",\"loanAmount\":99999}");
|
|
|
|
// when:
|
|
ResponseOptions response = given().spec(request)
|
|
.put("/fraudcheck");
|
|
|
|
// then:
|
|
assertThat(response.statusCode()).isEqualTo(200);
|
|
assertThat(response.header("Content-Type")).matches("application/vnd.fraud.v1.json.*");
|
|
// and:
|
|
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
|
assertThatJson(parsedJson).field("['fraudCheckStatus']").matches("[A-Z]{5}");
|
|
assertThatJson(parsedJson).field("['rejection.reason']").isEqualTo("Amount too high");
|
|
}
|
|
----
|
|
|
|
If you used the Groovy DSL, you can see that all the `producer()` parts of the Contract that were present in the
|
|
`value(consumer(...), producer(...))` blocks got injected into the test.
|
|
If you use YAML, the same applies 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,
|
|
headers, and body defined in the contract. It also expects precisely defined values
|
|
in the response. In other words, you have the `red` part of `red`, `green`, and
|
|
`refactor`. It is time to convert the `red` into the `green`.
|
|
|
|
[[getting-started-cdc-producer-impl]]
|
|
=== Write the Missing Implementation
|
|
|
|
Because you know the expected input and expected output, you can write the missing
|
|
implementation as follows:
|
|
|
|
[source,java,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=server_api,indent=0]
|
|
include::{samples_path}/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=new_impl,indent=0]
|
|
include::{samples_path}/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=initial_impl,indent=0]
|
|
}
|
|
----
|
|
|
|
When you run `./mvnw clean install` again, the tests pass. Since the Spring Cloud
|
|
Contract Verifier plugin adds the tests to the `generated-test-sources`, you can
|
|
actually run those tests from your IDE.
|
|
|
|
[[getting-started-cdc-producer-deploy]]
|
|
=== Deploying Your Application
|
|
|
|
Once you finish your work, you can deploy your changes. To do so, you must first merge the
|
|
branch by running the following commands:
|
|
|
|
[source,bash,indent=0]
|
|
----
|
|
$ git checkout master
|
|
$ git merge --no-ff contract-change-pr
|
|
$ git push origin master
|
|
----
|
|
|
|
Your CI might run a command such as `./mvnw clean deploy`, which would publish both the
|
|
application and the stub artifacts.
|
|
|
|
[[getting-started-cdc-consumer-final]]
|
|
== Consumer Side (Loan Issuance), Final Step
|
|
|
|
As a developer of the loan issuance service (a consumer of the Fraud Detection server), you need to:
|
|
|
|
- Merge our feature branch to `master`
|
|
- Switch to online mode of working
|
|
|
|
The following UML diagram shows the final state of the process:
|
|
|
|
[plantuml, getting-started-cdc-client-final, png]
|
|
----
|
|
"Loan\nIssuance"->"Loan\nIssuance": merge the\nfeature branch\nto master branch
|
|
"Loan\nIssuance"->"Loan\nIssuance": setup SCC Stub Runner\nto fetch stubs\nfrom Stub Storage
|
|
"Loan\nIssuance"->"LI\nSCC\nStub Runner": start stubs\nof FD from\nStub Storage
|
|
"LI\nSCC\nStub Runner"->"Stub Storage": find stubs of [FD]
|
|
"Stub Storage"->"LI\nSCC\nStub Runner": stubs of [FD] found
|
|
"LI\nSCC\nStub Runner"->"FD stub": run stubs of [FD]
|
|
"FD stub"->"LI\nSCC\nStub Runner": [FD] stub is running
|
|
"LI\nSCC\nStub Runner"->"Loan\nIssuance": stubs running and ready for the test
|
|
"Loan\nIssuance"->"Loan\nIssuance": run a test
|
|
"Loan\nIssuance"->"FD stub": the test\nsends a request\nto the running stub
|
|
"FD stub"->"Loan\nIssuance": stub responds successfuly
|
|
"Loan\nIssuance"->"Loan\nIssuance": the test passes successfully
|
|
----
|
|
|
|
[[getting-started-cdc-consumer-final-merge]]
|
|
=== Merging a Branch to Master
|
|
|
|
The following commands show one way to merge a branch into master with Git:
|
|
|
|
[source,bash,indent=0]
|
|
----
|
|
$ git checkout master
|
|
$ git merge --no-ff contract-change-pr
|
|
----
|
|
|
|
[[getting-started-cdc-consumer-final-online]]
|
|
=== Working Online
|
|
|
|
Now you can disable the offline work for Spring Cloud Contract Stub Runner and indicate
|
|
where the repository with your stubs is located. At this moment, the stubs of the server
|
|
side are automatically downloaded from Nexus/Artifactory. You can set the value of
|
|
`stubsMode` to `REMOTE`. The following code shows an example of
|
|
achieving the same thing by changing the properties:
|
|
|
|
[source,yaml,indent=0]
|
|
----
|
|
include::{samples_path}/standalone/dsl/http-client/src/test/resources/application-test-repo.yaml[]
|
|
----
|
|
|
|
That's it. You have finished the tutorial.
|
|
|