From 554d59bf917dc2d0ba7ffd11e1f4df3d954a4b8b Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Thu, 11 Jul 2019 17:00:25 +0200 Subject: [PATCH] WIP --- README.adoc | 420 ++++++---------- docs/src/main/asciidoc/README.adoc | 28 +- .../{building.adoc => _building.adoc} | 0 docs/src/main/asciidoc/_contract_flows.adoc | 8 + .../main/asciidoc/{links.adoc => _links.adoc} | 0 ...c => _spring-cloud-contract-verifier.adoc} | 17 +- ...emock.adoc => _spring-cloud-wiremock.adoc} | 25 +- ..._contract.adoc => _verifier_contract.adoc} | 124 +++-- .../{verifier_faq.adoc => _verifier_faq.adoc} | 2 +- ...ction.adoc => _verifier_how_it_works.adoc} | 204 ++------ .../main/asciidoc/_verifier_introduction.adoc | 120 +++++ ...essaging.adoc => _verifier_messaging.adoc} | 0 docs/src/main/asciidoc/_verifier_setup.adoc | 7 + ...brunner.adoc => _verifier_stubrunner.adoc} | 0 ...msg.adoc => _verifier_stubrunner_msg.adoc} | 0 docs/src/main/asciidoc/docker-project.adoc | 180 +++++++ docs/src/main/asciidoc/gradle-project.adoc | 420 ++++++++++++++++ ...verifier_setup.adoc => maven-project.adoc} | 475 ++---------------- docs/src/main/asciidoc/migrations.adoc | 180 ------- .../main/asciidoc/spring-cloud-contract.adoc | 11 +- 20 files changed, 1104 insertions(+), 1117 deletions(-) rename docs/src/main/asciidoc/{building.adoc => _building.adoc} (100%) create mode 100644 docs/src/main/asciidoc/_contract_flows.adoc rename docs/src/main/asciidoc/{links.adoc => _links.adoc} (100%) rename docs/src/main/asciidoc/{spring-cloud-contract-verifier.adoc => _spring-cloud-contract-verifier.adoc} (76%) rename docs/src/main/asciidoc/{spring-cloud-wiremock.adoc => _spring-cloud-wiremock.adoc} (92%) rename docs/src/main/asciidoc/{verifier_contract.adoc => _verifier_contract.adoc} (98%) rename docs/src/main/asciidoc/{verifier_faq.adoc => _verifier_faq.adoc} (99%) rename docs/src/main/asciidoc/{verifier_introduction.adoc => _verifier_how_it_works.adoc} (85%) create mode 100644 docs/src/main/asciidoc/_verifier_introduction.adoc rename docs/src/main/asciidoc/{verifier_messaging.adoc => _verifier_messaging.adoc} (100%) create mode 100644 docs/src/main/asciidoc/_verifier_setup.adoc rename docs/src/main/asciidoc/{verifier_stubrunner.adoc => _verifier_stubrunner.adoc} (100%) rename docs/src/main/asciidoc/{verifier_stubrunner_msg.adoc => _verifier_stubrunner_msg.adoc} (100%) create mode 100644 docs/src/main/asciidoc/docker-project.adoc create mode 100644 docs/src/main/asciidoc/gradle-project.adoc rename docs/src/main/asciidoc/{verifier_setup.adoc => maven-project.adoc} (66%) delete mode 100644 docs/src/main/asciidoc/migrations.adoc diff --git a/README.adoc b/README.adoc index 43c5b4f045..78c55fab50 100644 --- a/README.adoc +++ b/README.adoc @@ -8,8 +8,24 @@ Edit the files in the src/main/asciidoc/ directory instead. image::https://badges.gitter.im/Join%20Chat.svg[Gitter, link="https://gitter.im/spring-cloud/spring-cloud-contract?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] image::https://codecov.io/gh/spring-cloud/spring-cloud-contract/branch/{branch}/graph/badge.svg["codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-contract"] image::https://circleci.com/gh/spring-cloud/spring-cloud-contract.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-contract"] -:introduction_url: ../../../.. -:verifier_core_path: {introduction_url}/spring-cloud-contract-verifier +:branch: master +:core_path: ../../.. +:plugins_path: ../../../spring-cloud-contract-tools +:converters_path: {plugins_path}/spring-cloud-contract-converters +: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 +:samples_path: {core_path}/samples +:verifier_core_path: {verifier_root_path} +:stubrunner_core_path: {core_path}/spring-cloud-contract-stub-runner +:standalone_samples_path: {samples_path}/standalone/dsl +:standalone_messaging_samples_path: {samples_path}/standalone/messaging +:standalone_pact_path: {samples_path}/standalone/pact +:standalone_restdocs_path: {samples_path}/standalone/restdocs +:tests_path: {core_path}/tests +:samples_branch: 2.2.x +:samples_url: https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-contract-samples/{samples_branch} +:introduction_url: ${core_path}/../../ == Spring Cloud Contract @@ -27,23 +43,9 @@ https://cloud-samples.spring.io/spring-cloud-contract-samples/workshops.html[thi === Spring Cloud Contract Verifier -== Spring Cloud Contract Verifier Introduction +== Spring Cloud Contract Introduction -Spring Cloud Contract Verifier enables Consumer Driven Contract (CDC) development of -JVM-based applications. It moves TDD to the level of software architecture. - -Spring Cloud Contract Verifier ships with _Contract Definition Language_ (CDL). Contract -definitions are used to produce the following resources: - -* JSON stub definitions to be used by WireMock when doing integration testing on the -client code (_client tests_). Test code must still be written by hand, and test data is -produced by Spring Cloud Contract Verifier. -* Messaging routes, if you're using a messaging service. We integrate with Spring -Integration, Spring Cloud Stream, Spring AMQP, and Apache Camel. You can also set your -own integrations. -* Acceptance tests (in JUnit 4, JUnit 5 or Spock) are used to verify if server-side implementation -of the API is compliant with the contract (__server tests__). A full test is generated by -Spring Cloud Contract Verifier. +Spring Cloud Contract moves TDD to the level of software architecture. It allows to perform consumer, consumer-driven and producer-driven contract testing. === History @@ -71,6 +73,7 @@ Both have their advantages but also a lot of disadvantages. *Deploy all microservices and perform end to end tests* + Advantages: - Simulates production. @@ -99,29 +102,30 @@ Disadvantages: reality. - You can go to production with passing tests and failing production. -To solve the aforementioned issues, Spring Cloud Contract Verifier with Stub Runner was -created. The main idea is to give you very fast feedback, without the need to set up the +To solve the aforementioned issues, Spring Cloud Contract was created. The main idea is to give you very fast feedback, without the need to set up the whole world of microservices. If you work on stubs, then the only applications you need are those that your application directly uses. image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch}/docs/src/main/asciidoc/images/Stubs2.png[Stubbed Services] -Spring Cloud Contract Verifier gives you the certainty that the stubs that you use were +Spring Cloud Contract gives you the certainty that the stubs that you use were created by the service that you're calling. Also, if you can use them, it means that they were tested against the producer's side. In short, you can trust those stubs. === Purposes -The main purposes of Spring Cloud Contract Verifier with Stub Runner are: +The main purposes of Spring Cloud Contract are: -- To ensure that WireMock/Messaging stubs (used when developing the client) do exactly +- To ensure that Http / Messaging stubs (used when developing the client) do exactly what the actual server-side implementation does. -- To promote ATDD method and Microservices architectural style. +- To promote ATDD (acceptance test driven developement) method and Microservices architectural style. - To provide a way to publish changes in contracts that are immediately visible on both sides. - To generate boilerplate test code to be used on the server side. -IMPORTANT: Spring Cloud Contract Verifier's purpose is NOT to start writing business +By default Spring Cloud Contract integrates with http://wiremock.org[Wiremock] as the HTTP server stub. + +IMPORTANT: Spring Cloud Contract's purpose is NOT to start writing business features in the contracts. Assume that we have a business use case of fraud check. If a user can be a fraud for 100 different reasons, we would assume that you would create 2 contracts, one for the positive case and one for the negative case. Contract tests are @@ -129,7 +133,7 @@ used to test contracts between applications and not to simulate full behavior. === How It Works -This section explores how Spring Cloud Contract Verifier with Stub Runner works. +This section explores how Spring Cloud Contract. [[spring-cloud-contract-verifier-intro-three-second-tour]] ==== A Three-second Tour @@ -142,10 +146,28 @@ This very brief tour walks through using Spring Cloud Contract: You can find a somewhat longer tour <>. +[plantuml, three-second, png] +---- +"API Producer"->"API Producer": add Spring Cloud \nContract (SCC) plugin +"API Producer"->"API Producer": add SCC Verifier dependency +"API Producer"->"API Producer": define contracts +"API Producer"->"Build": run build +"Build"->"SCC Plugin": generate \ntests, stubs and stubs \nartifact (e.g. stubs-jar) +"Build"->"Nexus / Artifactory": upload contracts \nand stubs and the project arifact +"Build"->"API Producer": Build successful +"API Consumer"->"API Consumer": add SCC Stub Runner \ndependency +"API Consumer"->"API Consumer": write a SCC Stub Runner \nbased contract test +"SCC Stub Runner"->"Nexus / Artifactory": test asks for [API Producer] stubs +"Nexus / Artifactory"->"SCC Stub Runner": fetch the [API Producer] stubs +"SCC Stub Runner"->"SCC Stub Runner": run in memory\n HTTP server stubs +"API Consumer"->"SCC Stub Runner": send a request \nto the HTTP server stub +"SCC Stub Runner"->"API Consumer": communication is correct +---- + [[spring-cloud-contract-verifier-intro-three-second-tour-producer]] ===== On the Producer Side -To start working with Spring Cloud Contract, add files with `REST/` messaging contracts +To start working with Spring Cloud Contract, add files with `REST`/messaging contracts expressed in either Groovy DSL or YAML to the contracts directory, which is set by the `contractsDslDir` property. By default, it is `$rootDir/src/test/resources/contracts`. @@ -154,7 +176,7 @@ shown in the following example: [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=verifier_test_dependencies,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=verifier_test_dependencies,indent=0] ---- The following listing shows how to add the plugin, which should go in the build/plugins @@ -199,7 +221,7 @@ following example: [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/pom.xml[tags=stub_runner,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/pom.xml[tags=stub_runner,indent=0] ---- You can get the Producer-side stubs installed in your Maven repository in either of two @@ -221,9 +243,7 @@ Stub Runner` properties, as shown in the following example: + [source,yaml,indent=0] ---- -stubrunner: - ids: 'com.example:http-server-dsl:+:stubs:8080' - repositoryRoot: https://repo.spring.io/libs-snapshot +Unresolved directive in _verifier_how_it_works.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/samples/standalone/dsl/http-client/src/test/resources/application-test-repo.yaml[] ---- Now you can annotate your test class with `@AutoConfigureStubRunner`. In the annotation, @@ -265,9 +285,11 @@ expressed in either Groovy DSL or YAML to the contracts directory, which is set For the HTTP stubs, a contract defines what kind of response should be returned for a given request (taking into account the HTTP methods, URLs, headers, status codes, and so -on). The following example shows how an HTTP stub contract in Groovy DSL: +on). The following example shows how an HTTP stub contract: -[source,groovy,indent=0] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- package contracts @@ -296,9 +318,8 @@ org.springframework.cloud.contract.spec.Contract.make { } ---- -The same contract expressed in YAML would look like the following example: - -[source,yaml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- request: method: PUT @@ -321,6 +342,7 @@ response: headers: Content-Type: application/json;charset=UTF-8 ---- +==== In the case of messaging, you can define: @@ -329,26 +351,29 @@ was sent, the message body, and the header). * The methods that should be called after the message is received. * The methods that, when called, should trigger a message. -The following example shows a Camel messaging contract expressed in Groovy DSL: +The following example shows a Camel messaging contract: -[source,groovy] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- -Unresolved directive in verifier_introduction.adoc - include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_no_output_dsl] +Unresolved directive in _verifier_how_it_works.adoc - include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_no_output_dsl] ---- -The following example shows the same contract expressed in YAML: +[source,yaml,indent=0,role="secondary"] +.yaml +---- +Unresolved directive in _verifier_how_it_works.adoc - include::{verifier_core_path}/src/test/resources/yml/contract_message_scenario3.yml[indent=0] +---- +==== -[source,yml,indent=0] ----- -Unresolved directive in verifier_introduction.adoc - include::{verifier_core_path}/src/test/resources/yml/contract_message_scenario3.yml[indent=0] ----- Then you can add Spring Cloud Contract Verifier dependency and plugin to your build file, as shown in the following example: [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=verifier_test_dependencies,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=verifier_test_dependencies,indent=0] ---- The following listing shows how to add the plugin, which should go in the build/plugins @@ -404,7 +429,7 @@ In order to use `WebTestClient` set `testMode` to `WEBTESTCLIENT`. Here is an example of a test generated in `WEBTESTCLIENT` test mode: - [source,java,indent=0] +[source,java,indent=0] ---- @Test public void validate_shouldRejectABeerIfTooYoung() throws Exception { @@ -434,7 +459,7 @@ order number followed by an underscore at the beginning of the contract file nam The following example shows an auto-generated test in Spock for a messaging stub contract: - [source,groovy,indent=0] +[source,groovy,indent=0] ---- given: ContractVerifierMessage inputMessage = contractVerifierMessaging.create( @@ -503,7 +528,7 @@ To get started, add the dependency to `Spring Cloud Contract Stub Runner`: [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/pom.xml[tags=stub_runner,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/pom.xml[tags=stub_runner,indent=0] ---- You can get the Producer-side stubs installed in your Maven repository in either of two @@ -525,9 +550,7 @@ Runner` properties, as shown in the following example: + [source,yaml,indent=0] ---- -stubrunner: - ids: 'com.example:http-server-dsl:+:stubs:8080' - repositoryRoot: https://repo.spring.io/libs-snapshot +Unresolved directive in _verifier_how_it_works.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/samples/standalone/dsl/http-client/src/test/resources/application-test-repo.yaml[] ---- Now you can annotate your test class with `@AutoConfigureStubRunner`. In the annotation, @@ -570,17 +593,19 @@ 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/yml/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.yml[] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/yml/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.yml[] ---- +==== ==== Client Side @@ -592,14 +617,14 @@ At some point in time, you need to send a request to the Fraud Detection service [source,groovy,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java[tags=client_call_server,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java[tags=client_call_server,indent=0] ---- Annotate your test class with `@AutoConfigureStubRunner`. In the annotation provide the group id and artifact id for the Stub Runner to download stubs of your collaborators. [source,groovy,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java[tags=autoconfigure_stubrunner,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java[tags=autoconfigure_stubrunner,indent=0] ---- After that, during the tests, Spring Cloud Contract automatically finds the stubs @@ -671,13 +696,13 @@ following section to your build: [source,xml,indent=0,subs="verbatim,attributes",role="primary"] .Maven ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=repos,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=repos,indent=0] ---- [source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] .Gradle ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/build.gradle[tags=deps_repos,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/build.gradle[tags=deps_repos,indent=0] ---- ==== Consumer side (Loan Issuance) @@ -701,7 +726,7 @@ As a developer of the Loan Issuance service (a consumer of the Fraud Detection s [source,groovy,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java[tags=client_tdd,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/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 @@ -715,7 +740,7 @@ client wants to borrow. You want to send it to the `/fraudcheck` url via the `PU [source,groovy,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/src/main/java/com/example/loan/LoanApplicationService.java[tags=client_call_server,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/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 @@ -742,17 +767,19 @@ 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/yml/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.yml[] +Unresolved directive in _verifier_how_it_works.adoc - 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 @@ -790,14 +817,14 @@ First, add the `Spring Cloud Contract` BOM. [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=contract_bom,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=contract_bom,indent=0] ---- Next, add the `Spring Cloud Contract Verifier` Maven plugin [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=contract_maven_plugin,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/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, @@ -853,14 +880,14 @@ Add the `Spring Cloud Contract` BOM: [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/pom.xml[tags=contract_bom,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/pom.xml[tags=contract_bom,indent=0] ---- Add the dependency to `Spring Cloud Contract Stub Runner`: [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/pom.xml[tags=stub_runner,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/pom.xml[tags=stub_runner,indent=0] ---- Annotate your test class with `@AutoConfigureStubRunner`. In the annotation, provide the @@ -870,7 +897,7 @@ can also provide the offline work switch (`StubRunnerProperties.StubsMode.LOCAL` [source,groovy,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java[tags=autoconfigure_stubrunner,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-client/src/test/java/com/example/loan/LoanApplicationServiceTests.java[tags=autoconfigure_stubrunner,indent=0] ---- Now, when you run your tests, you see something like this: @@ -909,8 +936,8 @@ As a reminder, you can see the initial implementation here: [source,java,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=server_api,indent=0] -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=initial_impl,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=server_api,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=initial_impl,indent=0] } ---- @@ -926,14 +953,14 @@ You must add the dependencies needed by the autogenerated tests: [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=verifier_test_dependencies,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=verifier_test_dependencies,indent=0] ---- In the configuration of the Maven plugin, pass the `packageWithBaseClasses` property [source,xml,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=contract_maven_plugin,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/pom.xml[tags=contract_maven_plugin,indent=0] ---- IMPORTANT: This example uses "convention based" naming by setting the @@ -949,7 +976,7 @@ start the server side `FraudDetectionController`. [source,java,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudBase.java[] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/test/java/com/example/fraud/FraudBase.java[] ---- Now, if you run the `./mvnw clean install`, you get something like this: @@ -1006,9 +1033,9 @@ implementation: [source,java,indent=0] ---- -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=server_api,indent=0] -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=new_impl,indent=0] -Unresolved directive in verifier_introduction.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=initial_impl,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=server_api,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=new_impl,indent=0] +Unresolved directive in _verifier_how_it_works.adoc - include::{introduction_url}/samples/standalone/dsl/http-server/src/main/java/com/example/fraud/FraudDetectionController.java[tags=initial_impl,indent=0] } ---- @@ -1052,9 +1079,7 @@ achieving the same thing by changing the properties. [source,yaml,indent=0] ---- -stubrunner: - ids: 'com.example:http-server-dsl:+:stubs:8080' - repositoryRoot: https://repo.spring.io/libs-snapshot +Unresolved directive in _verifier_how_it_works.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/master/samples/standalone/dsl/http-client/src/test/resources/application-test-repo.yaml[] ---- That's it! @@ -1124,8 +1149,8 @@ your test. The following code shows an example: [source,java,indent=0] ---- -Unresolved directive in spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsTests.java[tags=wiremock_test1] -Unresolved directive in spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsTests.java[tags=wiremock_test2] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsTests.java[tags=wiremock_test1] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsTests.java[tags=wiremock_test2] ---- To start the stub server on a different port use (for example), @@ -1169,7 +1194,7 @@ stubs are stored under `/META-INF/group-id/artifact-id/versions/mappings/` folde [source,java,indent=0] ---- -Unresolved directive in spring-cloud-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockFilesApplicationWithUrlResourceTests.java[tags=load_all_stubs] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockFilesApplicationWithUrlResourceTests.java[tags=load_all_stubs] ---- === Using Files to Specify the Stub Bodies @@ -1197,8 +1222,8 @@ instance, as shown in the following example: [source,java,indent=0] ---- -Unresolved directive in spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsClassRuleTests.java[tags=wiremock_test1] -Unresolved directive in spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsClassRuleTests.java[tags=wiremock_test2] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsClassRuleTests.java[tags=wiremock_test1] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsClassRuleTests.java[tags=wiremock_test2] ---- The `@ClassRule` means that the server shuts down after all the methods in this class @@ -1260,7 +1285,7 @@ a Spring `MockRestServiceServer`. The following code shows an example: [source,java,indent=0] ---- -Unresolved directive in spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsMockServerApplicationTests.java[tags=wiremock_test] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{doc_samples}/src/test/java/com/example/WiremockForDocsMockServerApplicationTests.java[tags=wiremock_test] ---- The `baseUrl` value is prepended to all mock calls, and the `stubs()` method takes a stub @@ -1285,9 +1310,9 @@ Example: [source,java,indent=0] ---- -Unresolved directive in spring-cloud-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockConfigurationCustomizerTests.java[tags=customizer_1] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockConfigurationCustomizerTests.java[tags=customizer_1] // perform your customization here -Unresolved directive in spring-cloud-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockConfigurationCustomizerTests.java[tags=customizer_2] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockConfigurationCustomizerTests.java[tags=customizer_2] ---- === Generating Stubs using REST Docs @@ -1297,7 +1322,30 @@ documentation (for example in Asciidoctor format) for an HTTP API with Spring Mo or `WebTestClient` or Rest Assured. At the same time that you generate documentation for your API, you can also generate WireMock stubs by using Spring Cloud Contract WireMock. To do so, write your normal REST Docs test cases and use `@AutoConfigureRestDocs` to have stubs be -automatically generated in the REST Docs output directory. The following code shows an +automatically generated in the REST Docs output directory. + +[plantuml, rest-docs, png] +---- +"API Producer"->"API Producer": add Spring Cloud Contract (SCC) \nStub Runner dependency +"API Producer"->"API Producer": setup stub jar assembly +"API Producer"->"API Producer": write and setup REST Docs tests +"API Producer"->"Build": run build +"Build"->"REST Docs": generate API \ndocumentation +"REST Docs"->"SCC": generate stubs from the \nREST Docs tests +"REST Docs"->"SCC": generate contracts from the \nREST Docs tests +"Build"->"Build": assemble stubs jar with \nstubs and contracts +"Build"->"Nexus / Artifactory": upload contracts \nand stubs and the project arifact +"Build"->"API Producer": Build successful +"API Consumer"->"API Consumer": add SCC Stub Runner \ndependency +"API Consumer"->"API Consumer": write a SCC Stub Runner \nbased contract test +"SCC Stub Runner"->"Nexus / Artifactory": test asks for [API Producer] stubs +"Nexus / Artifactory"->"SCC Stub Runner": fetch the [API Producer] stubs +"SCC Stub Runner"->"SCC Stub Runner": run in memory\n HTTP server stubs +"API Consumer"->"SCC Stub Runner": send a request \nto the HTTP server stub +"SCC Stub Runner"->"API Consumer": communication is correct +---- + +The following code shows an example using `MockMvc`: [source,java,indent=0] @@ -1461,7 +1509,7 @@ Consider the following test: [source,java] ---- -Unresolved directive in spring-cloud-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java[tags=contract_snippet] +Unresolved directive in _spring-cloud-wiremock.adoc - include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java[tags=contract_snippet] ---- The preceding test creates the stub presented in the previous section, generating both @@ -1511,185 +1559,7 @@ You can read more about Spring Cloud Contract Verifier by reading the == Contributing -:spring-cloud-build-branch: master - -Spring Cloud is released under the non-restrictive Apache 2.0 license, -and follows a very standard Github development process, using Github -tracker for issues and merging pull requests into master. If you want -to contribute even something trivial please do not hesitate, but -follow the guidelines below. - -=== Sign the Contributor License Agreement -Before we accept a non-trivial patch or pull request we will need you to sign the -https://cla.pivotal.io/sign/spring[Contributor License Agreement]. -Signing the contributor's agreement does not grant anyone commit rights to the main -repository, but it does mean that we can accept your contributions, and you will get an -author credit if we do. Active contributors might be asked to join the core team, and -given the ability to merge pull requests. - -=== Code of Conduct -This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of -conduct]. By participating, you are expected to uphold this code. Please report -unacceptable behavior to spring-code-of-conduct@pivotal.io. - -=== Code Conventions and Housekeeping -None of these is essential for a pull request, but they will all help. They can also be -added after the original pull request but before a merge. - -* Use the Spring Framework code format conventions. If you use Eclipse - you can import formatter settings using the - `eclipse-code-formatter.xml` file from the - https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring - Cloud Build] project. If using IntelliJ, you can use the - https://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter - Plugin] to import the same file. -* Make sure all new `.java` files to have a simple Javadoc class comment with at least an - `@author` tag identifying you, and preferably at least a paragraph on what the class is - for. -* Add the ASF license header comment to all new `.java` files (copy from existing files - in the project) -* Add yourself as an `@author` to the .java files that you modify substantially (more - than cosmetic changes). -* Add some Javadocs and, if you change the namespace, some XSD doc elements. -* A few unit tests would help a lot as well -- someone has to do it. -* If no-one else is using your branch, please rebase it against the current master (or - other target branch in the main project). -* When writing a commit message please follow https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions], - if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit - message (where XXXX is the issue number). - -=== Checkstyle - -Spring Cloud Build comes with a set of checkstyle rules. You can find them in the `spring-cloud-build-tools` module. The most notable files under the module are: - -.spring-cloud-build-tools/ ----- -└── src -    ├── checkstyle -    │   └── checkstyle-suppressions.xml <3> -    └── main -    └── resources -    ├── checkstyle-header.txt <2> -    └── checkstyle.xml <1> ----- -<1> Default Checkstyle rules -<2> File header setup -<3> Default suppression rules - -==== Checkstyle configuration - -Checkstyle rules are *disabled by default*. To add checkstyle to your project just define the following properties and plugins. - -.pom.xml ----- - -true <1> - true - <2> - true - <3> - - - - - <4> - io.spring.javaformat - spring-javaformat-maven-plugin - - <5> - org.apache.maven.plugins - maven-checkstyle-plugin - - - - - - <5> - org.apache.maven.plugins - maven-checkstyle-plugin - - - - ----- -<1> Fails the build upon Checkstyle errors -<2> Fails the build upon Checkstyle violations -<3> Checkstyle analyzes also the test sources -<4> Add the Spring Java Format plugin that will reformat your code to pass most of the Checkstyle formatting rules -<5> Add checkstyle plugin to your build and reporting phases - -If you need to suppress some rules (e.g. line length needs to be longer), then it's enough for you to define a file under `${project.root}/src/checkstyle/checkstyle-suppressions.xml` with your suppressions. Example: - -.projectRoot/src/checkstyle/checkstyle-suppresions.xml ----- - - - - - - ----- - -It's advisable to copy the `${spring-cloud-build.rootFolder}/.editorconfig` and `${spring-cloud-build.rootFolder}/.springformat` to your project. That way, some default formatting rules will be applied. You can do so by running this script: - -```bash -$ curl https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/.editorconfig -o .editorconfig -$ touch .springformat -``` - -=== IDE setup - -==== Intellij IDEA - -In order to setup Intellij you should import our coding conventions, inspection profiles and set up the checkstyle plugin. -The following files can be found in the https://github.com/spring-cloud/spring-cloud-build/tree/master/spring-cloud-build-tools[Spring Cloud Build] project. - -.spring-cloud-build-tools/ ----- -└── src -    ├── checkstyle -    │   └── checkstyle-suppressions.xml <3> -    └── main -    └── resources -    ├── checkstyle-header.txt <2> -    ├── checkstyle.xml <1> -    └── intellij -       ├── Intellij_Project_Defaults.xml <4> -       └── Intellij_Spring_Boot_Java_Conventions.xml <5> ----- -<1> Default Checkstyle rules -<2> File header setup -<3> Default suppression rules -<4> Project defaults for Intellij that apply most of Checkstyle rules -<5> Project style conventions for Intellij that apply most of Checkstyle rules - -.Code style - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-code-style.png[Code style] - -Go to `File` -> `Settings` -> `Editor` -> `Code style`. There click on the icon next to the `Scheme` section. There, click on the `Import Scheme` value and pick the `Intellij IDEA code style XML` option. Import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Spring_Boot_Java_Conventions.xml` file. - -.Inspection profiles - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-inspections.png[Code style] - -Go to `File` -> `Settings` -> `Editor` -> `Inspections`. There click on the icon next to the `Profile` section. There, click on the `Import Profile` and import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Project_Defaults.xml` file. - -.Checkstyle - -To have Intellij work with Checkstyle, you have to install the `Checkstyle` plugin. It's advisable to also install the `Assertions2Assertj` to automatically convert the JUnit assertions - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-checkstyle.png[Checkstyle] - -Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on the `+` icon in the `Configuration file` section. There, you'll have to define where the checkstyle rules should be picked from. In the image above, we've picked the rules from the cloned Spring Cloud Build repository. However, you can point to the Spring Cloud Build's GitHub repository (e.g. for the `checkstyle.xml` : `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle.xml`). We need to provide the following variables: - -- `checkstyle.header.file` - please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/main/resources/checkstyle/checkstyle-header.txt` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` URL. -- `checkstyle.suppressions.file` - default suppressions. Please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` URL. -- `checkstyle.additional.suppressions.file` - this variable corresponds to suppressions in your local project. E.g. you're working on `spring-cloud-contract`. Then point to the `project-root/src/checkstyle/checkstyle-suppressions.xml` folder. Example for `spring-cloud-contract` would be: `/home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml`. - -IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources. +Unresolved directive in README.adoc - include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[] == How to build it diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc index cf91eb0f74..2c6fded0b4 100644 --- a/docs/src/main/asciidoc/README.adoc +++ b/docs/src/main/asciidoc/README.adoc @@ -2,8 +2,24 @@ image::https://badges.gitter.im/Join%20Chat.svg[Gitter, link="https://gitter.im/spring-cloud/spring-cloud-contract?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] image::https://codecov.io/gh/spring-cloud/spring-cloud-contract/branch/{branch}/graph/badge.svg["codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-contract"] image::https://circleci.com/gh/spring-cloud/spring-cloud-contract.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-contract"] -:introduction_url: ../../../.. -:verifier_core_path: {introduction_url}/spring-cloud-contract-verifier +:branch: master +:core_path: ../../.. +:plugins_path: ../../../spring-cloud-contract-tools +:converters_path: {plugins_path}/spring-cloud-contract-converters +: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 +:samples_path: {core_path}/samples +:verifier_core_path: {verifier_root_path} +:stubrunner_core_path: {core_path}/spring-cloud-contract-stub-runner +:standalone_samples_path: {samples_path}/standalone/dsl +:standalone_messaging_samples_path: {samples_path}/standalone/messaging +:standalone_pact_path: {samples_path}/standalone/pact +:standalone_restdocs_path: {samples_path}/standalone/restdocs +:tests_path: {core_path}/tests +:samples_branch: 2.2.x +:samples_url: https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-contract-samples/{samples_branch} +:introduction_url: ${core_path}/../../ == Spring Cloud Contract @@ -21,13 +37,13 @@ https://cloud-samples.spring.io/spring-cloud-contract-samples/workshops.html[thi === Spring Cloud Contract Verifier -include::verifier_introduction.adoc[] +include::_verifier_introduction.adoc[] -include::links.adoc[] +include::_links.adoc[] === Spring Cloud Contract WireMock -include::spring-cloud-wiremock.adoc[] +include::_spring-cloud-wiremock.adoc[] == Documentation @@ -38,4 +54,4 @@ You can read more about Spring Cloud Contract Verifier by reading the include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/docs/src/main/asciidoc/contributing.adoc[] -include::building.adoc[] +include::_building.adoc[] diff --git a/docs/src/main/asciidoc/building.adoc b/docs/src/main/asciidoc/_building.adoc similarity index 100% rename from docs/src/main/asciidoc/building.adoc rename to docs/src/main/asciidoc/_building.adoc diff --git a/docs/src/main/asciidoc/_contract_flows.adoc b/docs/src/main/asciidoc/_contract_flows.adoc new file mode 100644 index 0000000000..72ec8a01e5 --- /dev/null +++ b/docs/src/main/asciidoc/_contract_flows.adoc @@ -0,0 +1,8 @@ +- Provider contract testing with Maven / Gradle, stubs in artifactory +- Provider contract testing with Maven / Gradle, stubs in git +- Consumer Driven Contracts with contracts on the producer side +- Consumer Driven Contracts with contracts in external repo +- Consumer Driven Contracts with contracts and stubs in git +- Provider contract testing with Maven / Gradle, stubs in artifactory in non Spring world +- Provider contract testing with Maven / Gradle, stubs in artifactory in non JVM world +- Provider contract testing with REST Docs and with Maven / Gradle stubs in Artifactory \ No newline at end of file diff --git a/docs/src/main/asciidoc/links.adoc b/docs/src/main/asciidoc/_links.adoc similarity index 100% rename from docs/src/main/asciidoc/links.adoc rename to docs/src/main/asciidoc/_links.adoc diff --git a/docs/src/main/asciidoc/spring-cloud-contract-verifier.adoc b/docs/src/main/asciidoc/_spring-cloud-contract-verifier.adoc similarity index 76% rename from docs/src/main/asciidoc/spring-cloud-contract-verifier.adoc rename to docs/src/main/asciidoc/_spring-cloud-contract-verifier.adoc index 1dd900ca53..d8d9b6f29f 100644 --- a/docs/src/main/asciidoc/spring-cloud-contract-verifier.adoc +++ b/docs/src/main/asciidoc/_spring-cloud-contract-verifier.adoc @@ -1,3 +1,4 @@ +:branch: master :core_path: ../../.. :plugins_path: ../../../spring-cloud-contract-tools :converters_path: {plugins_path}/spring-cloud-contract-converters @@ -12,20 +13,20 @@ :standalone_pact_path: {samples_path}/standalone/pact :standalone_restdocs_path: {samples_path}/standalone/restdocs :tests_path: {core_path}/tests -:samples_branch: 2.1.x +:samples_branch: 2.2.x :samples_url: https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-contract-samples/{samples_branch} :introduction_url: ${core_path}/../../ -include::verifier_introduction.adoc[] +include::_verifier_introduction.adoc[] -include::verifier_faq.adoc[] +include::_verifier_faq.adoc[] -include::verifier_setup.adoc[] +include::_verifier_setup.adoc[] -include::verifier_messaging.adoc[] +include::_verifier_messaging.adoc[] -include::verifier_stubrunner.adoc[] +include::_verifier_stubrunner.adoc[] -include::verifier_stubrunner_msg.adoc[] +include::_verifier_stubrunner_msg.adoc[] -include::verifier_contract.adoc[] \ No newline at end of file +include::_verifier_contract.adoc[] \ No newline at end of file diff --git a/docs/src/main/asciidoc/spring-cloud-wiremock.adoc b/docs/src/main/asciidoc/_spring-cloud-wiremock.adoc similarity index 92% rename from docs/src/main/asciidoc/spring-cloud-wiremock.adoc rename to docs/src/main/asciidoc/_spring-cloud-wiremock.adoc index 9ad7e9b200..e4203362c6 100644 --- a/docs/src/main/asciidoc/spring-cloud-wiremock.adoc +++ b/docs/src/main/asciidoc/_spring-cloud-wiremock.adoc @@ -191,7 +191,30 @@ documentation (for example in Asciidoctor format) for an HTTP API with Spring Mo or `WebTestClient` or Rest Assured. At the same time that you generate documentation for your API, you can also generate WireMock stubs by using Spring Cloud Contract WireMock. To do so, write your normal REST Docs test cases and use `@AutoConfigureRestDocs` to have stubs be -automatically generated in the REST Docs output directory. The following code shows an +automatically generated in the REST Docs output directory. + +[plantuml, rest-docs, png] +---- +"API Producer"->"API Producer": add Spring Cloud Contract (SCC) \nStub Runner dependency +"API Producer"->"API Producer": setup stub jar assembly +"API Producer"->"API Producer": write and setup REST Docs tests +"API Producer"->"Build": run build +"Build"->"REST Docs": generate API \ndocumentation +"REST Docs"->"SCC": generate stubs from the \nREST Docs tests +"REST Docs"->"SCC": generate contracts from the \nREST Docs tests +"Build"->"Build": assemble stubs jar with \nstubs and contracts +"Build"->"Nexus / Artifactory": upload contracts \nand stubs and the project arifact +"Build"->"API Producer": Build successful +"API Consumer"->"API Consumer": add SCC Stub Runner \ndependency +"API Consumer"->"API Consumer": write a SCC Stub Runner \nbased contract test +"SCC Stub Runner"->"Nexus / Artifactory": test asks for [API Producer] stubs +"Nexus / Artifactory"->"SCC Stub Runner": fetch the [API Producer] stubs +"SCC Stub Runner"->"SCC Stub Runner": run in memory\n HTTP server stubs +"API Consumer"->"SCC Stub Runner": send a request \nto the HTTP server stub +"SCC Stub Runner"->"API Consumer": communication is correct +---- + +The following code shows an example using `MockMvc`: [source,java,indent=0] diff --git a/docs/src/main/asciidoc/verifier_contract.adoc b/docs/src/main/asciidoc/_verifier_contract.adoc similarity index 98% rename from docs/src/main/asciidoc/verifier_contract.adoc rename to docs/src/main/asciidoc/_verifier_contract.adoc index ee2eaa7fb2..2ca22db220 100644 --- a/docs/src/main/asciidoc/verifier_contract.adoc +++ b/docs/src/main/asciidoc/_verifier_contract.adoc @@ -64,17 +64,19 @@ 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{contract_spec_tests_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=description,indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- include::{verifier_core_path}/src/test/resources/yml/contract_rest.yml[indent=0] ---- +==== [[contract-dsl-name]] ==== Name @@ -89,17 +91,19 @@ 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{contract_spec_tests_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=name,indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=name,indent=0] ---- +==== [[contract-dsl-ignoring-contracts]] ==== Ignoring Contracts @@ -107,17 +111,19 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=name,inde 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{contract_spec_tests_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=ignored,indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=ignored,indent=0] ---- +==== [[contract-dsl-passing-values-from-files]] ==== Passing Values from Files @@ -138,17 +144,19 @@ following resources in our project. Further assume that your contract is as follows: -.Groovy DSL -[source,groovy,indent=0] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{verifier_core_path}/src/test/resources/classpath/readFromFile.groovy[indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- include::{verifier_core_path}/src/test/resources/yml/contract_from_file.yml[indent=0] ---- +==== Further assume that the JSON files is as follows: @@ -171,17 +179,19 @@ relative to the folder in which the contract lays. If you need to pass the contents of a file in a binary form it's enough for you to use the `fileAsBytes` method in Groovy DSL or `bodyFromFileAsBytes` field in YAML. -.Groovy DSL -[source,groovy,indent=0] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{verifier_core_path}/src/test/resources/body_builder/worksWithPdf.groovy[indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- include::{verifier_core_path}/src/test/resources/yml/contract_pdf.yml[indent=0] ---- +==== IMPORTANT: You should use this approach whenever you want to work with binary payloads both for HTTP and messaging. @@ -216,32 +226,36 @@ value `5` has **higher** priority than `priority` with value `10`. 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=request,indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=url,indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- include::{verifier_core_path}/src/test/resources/yml/contract_rest_with_path.yml[tags=url_path,indent=0] ---- +==== `request` may contain **query parameters**. @@ -310,17 +324,19 @@ include::{verifier_core_path}/src/test/resources/yml/contract.yml[tags=body,inde `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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy[tags=multipartdsl,indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- 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: @@ -657,17 +673,19 @@ matches the JSON Path. E.g. for json path `$.foo` - `{{{ jsonpath this '$.foo' } Consider the following contract: -.Groovy DSL -[source,groovy,indent=0] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy[tags=template_contract,indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- 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: @@ -911,17 +929,19 @@ You can also define which type the regular expression corresponds to via the `re Consider the following example: -.Groovy DSL -[source,groovy,indent=0] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy[tags=matchers,indent=0] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- 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 @@ -1419,17 +1439,19 @@ in the generated test. You can define multiple contracts in one file. Such a contract might resemble the following example: -.Groovy DSL -[source,groovy,indent=0] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- 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] +[source,yaml,indent=0,role="secondary"] +.yaml ---- 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: @@ -1534,14 +1556,14 @@ include::{standalone_restdocs_path}/http-server/src/test/java/com/example/fraud/ TIP: You don't need to specify the output directory for the generated snippets since version 1.2.0.RELEASE of Spring REST Docs. -== Customization +=== DSL 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. -=== Extending the DSL +==== Extending the DSL You can provide your own functions to the DSL. The key requirement for this feature is to maintain the static compatibility. Later in this document, you can see examples of: @@ -1552,7 +1574,7 @@ maintain the static compatibility. Later in this document, you can see examples You can find the full example https://github.com/spring-cloud-samples/spring-cloud-contract-samples[here]. -==== Common JAR +===== Common JAR The following examples show three classes that can be reused in the DSLs. @@ -1577,14 +1599,14 @@ include::{samples_url}/common/src/main/java/com/example/ConsumerUtils.java[] include::{samples_url}/common/src/main/java/com/example/ProducerUtils.java[] ---- -==== Adding the Dependency to the Project +===== Adding the Dependency to the Project In order for the plugins and IDE to be able to reference the common JAR classes, you need to pass the dependency to your project. // TODO missing code block here - we should show an example adding a dependency -==== Test the Dependency in the Project's Dependencies +===== Test the Dependency in the Project's Dependencies First, add the common jar dependency as a test dependency. Because your contracts files are available on the test resources path, the common jar classes automatically become @@ -1602,7 +1624,7 @@ include::{samples_url}/producer/pom.xml[tags=test_dep,indent=0] include::{samples_url}/producer/build.gradle[tags=test_dep,indent=0] ---- -==== Test a Dependency in the Plugin's Dependencies +===== Test a Dependency in the Plugin's Dependencies Now, you must add the dependency for the plugin to reuse at runtime, as shown in the following example: @@ -1619,7 +1641,7 @@ include::{samples_url}/producer/pom.xml[tags=test_dep_in_plugin,indent=0] include::{samples_url}/producer/build.gradle[tags=test_dep_in_plugin,indent=0] ---- -==== Referencing classes in DSLs +===== Referencing classes in DSLs You can now reference your classes in your DSL, as shown in the following example: diff --git a/docs/src/main/asciidoc/verifier_faq.adoc b/docs/src/main/asciidoc/_verifier_faq.adoc similarity index 99% rename from docs/src/main/asciidoc/verifier_faq.adoc rename to docs/src/main/asciidoc/_verifier_faq.adoc index 2c17140c21..97ac27ecee 100644 --- a/docs/src/main/asciidoc/verifier_faq.adoc +++ b/docs/src/main/asciidoc/_verifier_faq.adoc @@ -1,5 +1,5 @@ :introduction_url: https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch} -:samples_branch: 2.1.x +:samples_branch: 2.2.x == Spring Cloud Contract FAQ diff --git a/docs/src/main/asciidoc/verifier_introduction.adoc b/docs/src/main/asciidoc/_verifier_how_it_works.adoc similarity index 85% rename from docs/src/main/asciidoc/verifier_introduction.adoc rename to docs/src/main/asciidoc/_verifier_how_it_works.adoc index f2342dd43f..eeff07d9c6 100644 --- a/docs/src/main/asciidoc/verifier_introduction.adoc +++ b/docs/src/main/asciidoc/_verifier_how_it_works.adoc @@ -1,106 +1,6 @@ -== Spring Cloud Contract Verifier Introduction - -Spring Cloud Contract Verifier enables Consumer Driven Contract (CDC) development of -JVM-based applications. It moves TDD to the level of software architecture. - -Spring Cloud Contract Verifier ships with _Contract Definition Language_ (CDL). Contract -definitions are used to produce the following resources: - -* JSON stub definitions to be used by WireMock when doing integration testing on the -client code (_client tests_). Test code must still be written by hand, and test data is -produced by Spring Cloud Contract Verifier. -* Messaging routes, if you're using a messaging service. We integrate with Spring -Integration, Spring Cloud Stream, Spring AMQP, and Apache Camel. You can also set your -own integrations. -* Acceptance tests (in JUnit 4, JUnit 5 or Spock) are used to verify if server-side implementation -of the API is compliant with the contract (__server tests__). A full test is generated by -Spring Cloud Contract Verifier. - -=== History - -Before becoming Spring Cloud Contract, this project was called https://github.com/Codearte/accurest[Accurest]. -It was created by https://twitter.com/mgrzejszczak[Marcin Grzejszczak] and https://twitter.com/jkubrynski[Jakub Kubrynski] -from (https://github.com/Codearte[Codearte]. - -The `0.1.0` release took place on 26 Jan 2015 and it became stable with `1.0.0` release on 29 Feb 2016. - -=== Why a Contract Verifier? - -Assume that we have a system consisting of multiple microservices: - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch}/docs/src/main/asciidoc/images/Deps.png[Microservices Architecture] - -==== Testing issues - -If we wanted to test the application in top left corner to determine whether it can -communicate with other services, we could do one of two things: - -- Deploy all microservices and perform end-to-end tests. -- Mock other microservices in unit/integration tests. - -Both have their advantages but also a lot of disadvantages. - -*Deploy all microservices and perform end to end tests* - -Advantages: - -- Simulates production. -- Tests real communication between services. - -Disadvantages: - -- To test one microservice, we have to deploy 6 microservices, a couple of databases, -etc. -- The environment where the tests run is locked for a single suite of tests (nobody else -would be able to run the tests in the meantime). -- They take a long time to run. -- The feedback comes very late in the process. -- They are extremely hard to debug. - -*Mock other microservices in unit/integration tests* - -Advantages: - -- They provide very fast feedback. -- They have no infrastructure requirements. - -Disadvantages: - -- The implementor of the service creates stubs that might have nothing to do with -reality. -- You can go to production with passing tests and failing production. - -To solve the aforementioned issues, Spring Cloud Contract Verifier with Stub Runner was -created. The main idea is to give you very fast feedback, without the need to set up the -whole world of microservices. If you work on stubs, then the only applications you need -are those that your application directly uses. - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch}/docs/src/main/asciidoc/images/Stubs2.png[Stubbed Services] - -Spring Cloud Contract Verifier gives you the certainty that the stubs that you use were -created by the service that you're calling. Also, if you can use them, it means that they -were tested against the producer's side. In short, you can trust those stubs. - -=== Purposes - -The main purposes of Spring Cloud Contract Verifier with Stub Runner are: - -- To ensure that WireMock/Messaging stubs (used when developing the client) do exactly -what the actual server-side implementation does. -- To promote ATDD method and Microservices architectural style. -- To provide a way to publish changes in contracts that are immediately visible on both -sides. -- To generate boilerplate test code to be used on the server side. - -IMPORTANT: Spring Cloud Contract Verifier's purpose is NOT to start writing business -features in the contracts. Assume that we have a business use case of fraud check. If a -user can be a fraud for 100 different reasons, we would assume that you would create 2 -contracts, one for the positive case and one for the negative case. Contract tests are -used to test contracts between applications and not to simulate full behavior. - === How It Works -This section explores how Spring Cloud Contract Verifier with Stub Runner works. +This section explores how Spring Cloud Contract. [[spring-cloud-contract-verifier-intro-three-second-tour]] ==== A Three-second Tour @@ -113,10 +13,28 @@ This very brief tour walks through using Spring Cloud Contract: You can find a somewhat longer tour <>. +[plantuml, three-second, png] +---- +"API Producer"->"API Producer": add Spring Cloud \nContract (SCC) plugin +"API Producer"->"API Producer": add SCC Verifier dependency +"API Producer"->"API Producer": define contracts +"API Producer"->"Build": run build +"Build"->"SCC Plugin": generate \ntests, stubs and stubs \nartifact (e.g. stubs-jar) +"Build"->"Nexus / Artifactory": upload contracts \nand stubs and the project arifact +"Build"->"API Producer": Build successful +"API Consumer"->"API Consumer": add SCC Stub Runner \ndependency +"API Consumer"->"API Consumer": write a SCC Stub Runner \nbased contract test +"SCC Stub Runner"->"Nexus / Artifactory": test asks for [API Producer] stubs +"Nexus / Artifactory"->"SCC Stub Runner": fetch the [API Producer] stubs +"SCC Stub Runner"->"SCC Stub Runner": run in memory\n HTTP server stubs +"API Consumer"->"SCC Stub Runner": send a request \nto the HTTP server stub +"SCC Stub Runner"->"API Consumer": communication is correct +---- + [[spring-cloud-contract-verifier-intro-three-second-tour-producer]] ===== On the Producer Side -To start working with Spring Cloud Contract, add files with `REST/` messaging contracts +To start working with Spring Cloud Contract, add files with `REST`/messaging contracts expressed in either Groovy DSL or YAML to the contracts directory, which is set by the `contractsDslDir` property. By default, it is `$rootDir/src/test/resources/contracts`. @@ -234,9 +152,11 @@ expressed in either Groovy DSL or YAML to the contracts directory, which is set For the HTTP stubs, a contract defines what kind of response should be returned for a given request (taking into account the HTTP methods, URLs, headers, status codes, and so -on). The following example shows how an HTTP stub contract in Groovy DSL: +on). The following example shows how an HTTP stub contract: -[source,groovy,indent=0] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- package contracts @@ -265,9 +185,8 @@ org.springframework.cloud.contract.spec.Contract.make { } ---- -The same contract expressed in YAML would look like the following example: - -[source,yaml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- request: method: PUT @@ -290,6 +209,7 @@ response: headers: Content-Type: application/json;charset=UTF-8 ---- +==== In the case of messaging, you can define: @@ -298,19 +218,22 @@ was sent, the message body, and the header). * The methods that should be called after the message is received. * The methods that, when called, should trigger a message. -The following example shows a Camel messaging contract expressed in Groovy DSL: +The following example shows a Camel messaging contract: -[source,groovy] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_no_output_dsl] ---- -The following example shows the same contract expressed in YAML: - -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- include::{verifier_core_path}/src/test/resources/yml/contract_message_scenario3.yml[indent=0] ---- +==== + Then you can add Spring Cloud Contract Verifier dependency and plugin to your build file, as shown in the following example: @@ -373,7 +296,7 @@ In order to use `WebTestClient` set `testMode` to `WEBTESTCLIENT`. Here is an example of a test generated in `WEBTESTCLIENT` test mode: - [source,java,indent=0] +[source,java,indent=0] ---- @Test public void validate_shouldRejectABeerIfTooYoung() throws Exception { @@ -403,7 +326,7 @@ order number followed by an underscore at the beginning of the contract file nam The following example shows an auto-generated test in Spock for a messaging stub contract: - [source,groovy,indent=0] +[source,groovy,indent=0] ---- given: ContractVerifierMessage inputMessage = contractVerifierMessaging.create( @@ -537,17 +460,19 @@ 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- include::{introduction_url}/samples/standalone/yml/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.yml[] ---- +==== ==== Client Side @@ -709,17 +634,19 @@ 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] +==== +[source,groovy,indent=0,role="primary"] +.groovy ---- include::{introduction_url}/samples/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[] ---- -.YAML -[source,yml,indent=0] +[source,yaml,indent=0,role="secondary"] +.yaml ---- 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 @@ -1022,35 +949,4 @@ achieving the same thing by changing the properties. include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch}/samples/standalone/dsl/http-client/src/test/resources/application-test-repo.yaml[] ---- -That's it! - -=== Dependencies - -The best way to add dependencies is to use the proper `starter` dependency. - -For `stub-runner`, use `spring-cloud-starter-stub-runner`. When you use a plugin, add -`spring-cloud-starter-contract-verifier`. - -=== Additional Links - -Here are some resources related to Spring Cloud Contract Verifier and Stub Runner. Note -that some may be outdated, because the Spring Cloud Contract Verifier project is under -constant development. - -==== Spring Cloud Contract video - -You can check out the video from the Warsaw JUG about Spring Cloud Contract: - -video::sAAklvxmPmk[youtube,start=538,width=640,height=480] - -==== Readings - -- https://www.slideshare.net/MarcinGrzejszczak/stick-to-the-rules-consumer-driven-contracts-201507-confitura[Slides from Marcin Grzejszczak's talk about Accurest] -- https://toomuchcoding.com/blog/categories/accurest/[Accurest related articles from Marcin Grzejszczak's blog] -- https://toomuchcoding.com/blog/categories/spring-cloud-contract/[Spring Cloud Contract related articles from Marcin Grzejszczak's blog] -- https://groovy-lang.org/json.html[Groovy docs regarding JSON] - -=== Samples - -You can find some samples at -https://github.com/spring-cloud-samples/spring-cloud-contract-samples[samples]. +That's it! \ No newline at end of file diff --git a/docs/src/main/asciidoc/_verifier_introduction.adoc b/docs/src/main/asciidoc/_verifier_introduction.adoc new file mode 100644 index 0000000000..466d8ad150 --- /dev/null +++ b/docs/src/main/asciidoc/_verifier_introduction.adoc @@ -0,0 +1,120 @@ +== Spring Cloud Contract Introduction + +Spring Cloud Contract moves TDD to the level of software architecture. It allows to perform consumer, consumer-driven and producer-driven contract testing. + +=== History + +Before becoming Spring Cloud Contract, this project was called https://github.com/Codearte/accurest[Accurest]. +It was created by https://twitter.com/mgrzejszczak[Marcin Grzejszczak] and https://twitter.com/jkubrynski[Jakub Kubrynski] +from (https://github.com/Codearte[Codearte]. + +The `0.1.0` release took place on 26 Jan 2015 and it became stable with `1.0.0` release on 29 Feb 2016. + +=== Why a Contract Verifier? + +Assume that we have a system consisting of multiple microservices: + +image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch}/docs/src/main/asciidoc/images/Deps.png[Microservices Architecture] + +==== Testing issues + +If we wanted to test the application in top left corner to determine whether it can +communicate with other services, we could do one of two things: + +- Deploy all microservices and perform end-to-end tests. +- Mock other microservices in unit/integration tests. + +Both have their advantages but also a lot of disadvantages. + +*Deploy all microservices and perform end to end tests* + + +Advantages: + +- Simulates production. +- Tests real communication between services. + +Disadvantages: + +- To test one microservice, we have to deploy 6 microservices, a couple of databases, +etc. +- The environment where the tests run is locked for a single suite of tests (nobody else +would be able to run the tests in the meantime). +- They take a long time to run. +- The feedback comes very late in the process. +- They are extremely hard to debug. + +*Mock other microservices in unit/integration tests* + +Advantages: + +- They provide very fast feedback. +- They have no infrastructure requirements. + +Disadvantages: + +- The implementor of the service creates stubs that might have nothing to do with +reality. +- You can go to production with passing tests and failing production. + +To solve the aforementioned issues, Spring Cloud Contract was created. The main idea is to give you very fast feedback, without the need to set up the +whole world of microservices. If you work on stubs, then the only applications you need +are those that your application directly uses. + +image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/{branch}/docs/src/main/asciidoc/images/Stubs2.png[Stubbed Services] + +Spring Cloud Contract gives you the certainty that the stubs that you use were +created by the service that you're calling. Also, if you can use them, it means that they +were tested against the producer's side. In short, you can trust those stubs. + +=== Purposes + +The main purposes of Spring Cloud Contract are: + +- To ensure that Http / Messaging stubs (used when developing the client) do exactly +what the actual server-side implementation does. +- To promote ATDD (acceptance test driven developement) method and Microservices architectural style. +- To provide a way to publish changes in contracts that are immediately visible on both +sides. +- To generate boilerplate test code to be used on the server side. + +By default Spring Cloud Contract integrates with http://wiremock.org[Wiremock] as the HTTP server stub. + +IMPORTANT: Spring Cloud Contract's purpose is NOT to start writing business +features in the contracts. Assume that we have a business use case of fraud check. If a +user can be a fraud for 100 different reasons, we would assume that you would create 2 +contracts, one for the positive case and one for the negative case. Contract tests are +used to test contracts between applications and not to simulate full behavior. + +include::_verifier_how_it_works.adoc[] + +=== Dependencies + +The best way to add dependencies is to use the proper `starter` dependency. + +For `stub-runner`, use `spring-cloud-starter-stub-runner`. When you use a plugin, add +`spring-cloud-starter-contract-verifier`. + +=== Additional Links + +Here are some resources related to Spring Cloud Contract Verifier and Stub Runner. Note +that some may be outdated, because the Spring Cloud Contract Verifier project is under +constant development. + +==== Spring Cloud Contract video + +You can check out the video from the Warsaw JUG about Spring Cloud Contract: + +video::sAAklvxmPmk[youtube,start=538,width=640,height=480] + +==== Readings + +- https://www.slideshare.net/MarcinGrzejszczak/stick-to-the-rules-consumer-driven-contracts-201507-confitura[Slides from Marcin Grzejszczak's talk about Accurest] +- https://toomuchcoding.com/blog/categories/accurest/[Accurest related articles from Marcin Grzejszczak's blog] +- https://toomuchcoding.com/blog/categories/spring-cloud-contract/[Spring Cloud Contract related articles from Marcin Grzejszczak's blog] +- https://groovy-lang.org/json.html[Groovy docs regarding JSON] + +=== Samples + +You can find some samples at +https://github.com/spring-cloud-samples/spring-cloud-contract-samples[samples]. diff --git a/docs/src/main/asciidoc/verifier_messaging.adoc b/docs/src/main/asciidoc/_verifier_messaging.adoc similarity index 100% rename from docs/src/main/asciidoc/verifier_messaging.adoc rename to docs/src/main/asciidoc/_verifier_messaging.adoc diff --git a/docs/src/main/asciidoc/_verifier_setup.adoc b/docs/src/main/asciidoc/_verifier_setup.adoc new file mode 100644 index 0000000000..e805a2d1c7 --- /dev/null +++ b/docs/src/main/asciidoc/_verifier_setup.adoc @@ -0,0 +1,7 @@ +== Spring Cloud Contract Verifier Setup + +You can set up Spring Cloud Contract Verifier in the following ways: + +* link:gradle-project.html[As a Gradle project] +* link:maven-project.html[As a Maven project] +* link:docker-project.html[As a Docker project] \ No newline at end of file diff --git a/docs/src/main/asciidoc/verifier_stubrunner.adoc b/docs/src/main/asciidoc/_verifier_stubrunner.adoc similarity index 100% rename from docs/src/main/asciidoc/verifier_stubrunner.adoc rename to docs/src/main/asciidoc/_verifier_stubrunner.adoc diff --git a/docs/src/main/asciidoc/verifier_stubrunner_msg.adoc b/docs/src/main/asciidoc/_verifier_stubrunner_msg.adoc similarity index 100% rename from docs/src/main/asciidoc/verifier_stubrunner_msg.adoc rename to docs/src/main/asciidoc/_verifier_stubrunner_msg.adoc diff --git a/docs/src/main/asciidoc/docker-project.adoc b/docs/src/main/asciidoc/docker-project.adoc new file mode 100644 index 0000000000..4eca6a5220 --- /dev/null +++ b/docs/src/main/asciidoc/docker-project.adoc @@ -0,0 +1,180 @@ += Docker Project + +We're publishing a `springcloud/spring-cloud-contract` Docker image +that contains a project that will generate tests and execute them in `EXPLICIT` mode +against a running application. + +TIP: The `EXPLICIT` mode means that the tests generated from contracts will send +real requests and not the mocked ones. + +== Short intro to Maven, JARs and Binary storage + +Since the Docker image can be used by non JVM projects, it's good to +explain the basic terms behind Spring Cloud Contract packaging defaults. + +Part of the following definitions were taken from the https://maven.apache.org/glossary.html[Maven Glossary] + +- `Project`: Maven thinks in terms of projects. Everything that you +will build are projects. Those projects follow a well defined +“Project Object Model”. Projects can depend on other projects, +in which case the latter are called “dependencies”. A project may +consistent of several subprojects, however these subprojects are still +treated equally as projects. +- `Artifact`: An artifact is something that is either produced or used +by a project. Examples of artifacts produced by Maven for a project +include: JARs, source and binary distributions. Each artifact +is uniquely identified by a group id and an artifact ID which is +unique within a group. +- `JAR`: JAR stands for Java ARchive. It's a format based on +the ZIP file format. Spring Cloud Contract packages the contracts and generated +stubs in a JAR file. +- `GroupId`: A group ID is a universally unique identifier for a project. +While this is often just the project name (eg. commons-collections), +it is helpful to use a fully-qualified package name to distinguish it +from other projects with a similar name (eg. org.apache.maven). +Typically, when published to the Artifact Manager, the `GroupId` will get +slash separated and form part of the URL. E.g. for group id `com.example` +and artifact id `application` would be `/com/example/application/`. +- `Classifier`: The Maven dependency notation looks as follows: +`groupId:artifactId:version:classifier`. The classifier is additional suffix +passed to the dependency. E.g. `stubs`, `sources`. The same dependency +e.g. `com.example:application` can produce multiple artifacts that +differ from each other with the classifier. +- `Artifact manager`: When you generate binaries / sources / packages, you would +like them to be available for others to download / reference or reuse. In case +of the JVM world those artifacts would be JARs, for Ruby these are gems +and for Docker those would be Docker images. You can store those artifacts +in a manager. Examples of such managers can be https://jfrog.com/artifactory/[Artifactory] +or https://www.sonatype.org/nexus/[Nexus]. + +== How it works + +The image searches for contracts under the `/contracts` folder. +The output from running the tests will be available under +`/spring-cloud-contract/build` folder (it's useful for debugging +purposes). + +It's enough for you to mount your contracts, pass the environment variables + and the image will: + +- generate the contract tests +- execute the tests against the provided URL +- generate the https://github.com/tomakehurst/wiremock[WireMock] stubs +- (optional - turned on by default) publish the stubs to a Artifact Manager + +=== Environment Variables + +The Docker image requires some environment variables to point to +your running application, to the Artifact manager instance etc. + +- `PROJECT_GROUP` - your project's group id. Defaults to `com.example` +- `PROJECT_VERSION` - your project's version. Defaults to `0.0.1-SNAPSHOT` +- `PROJECT_NAME` - artifact id. Defaults to `example` +- `PRODUCER_STUBS_CLASSIFIER` - archive classifier used for generated producer stubs, defaults to `stubs`. +- `REPO_WITH_BINARIES_URL` - URL of your Artifact Manager. Defaults to `http://localhost:8081/artifactory/libs-release-local` +which is the default URL of https://jfrog.com/artifactory/[Artifactory] running locally +- `REPO_WITH_BINARIES_USERNAME` - (optional) username when the Artifact Manager is secured, defaults to `admin`. +- `REPO_WITH_BINARIES_PASSWORD` - (optional) password when the Artifact Manager is secured, defaults to `password`. +- `PUBLISH_ARTIFACTS` - if set to `true` then will publish artifact to binary storage. Defaults to `true`. + +These environment variables are used when contracts lay in an external repository. To enable +this feature you must set the `EXTERNAL_CONTRACTS_ARTIFACT_ID` environment variable. + +- `EXTERNAL_CONTRACTS_GROUP_ID` - group id of the project with contracts. Defaults to `com.example` +- `EXTERNAL_CONTRACTS_ARTIFACT_ID`- artifact id of the project with contracts. +- `EXTERNAL_CONTRACTS_CLASSIFIER`- classifier of the project with contracts. Empty by default +- `EXTERNAL_CONTRACTS_VERSION` - version of the project with contracts. Defaults to `+`, equivalent to picking the latest +- `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL` - URL of your Artifact Manager. Defaults to value of `REPO_WITH_BINARIES_URL` env var. +If that's not set, defaults to `http://localhost:8081/artifactory/libs-release-local` +which is the default URL of https://jfrog.com/artifactory/[Artifactory] running locally +- `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_USERNAME` - (optional) username if the `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL` +requires authentication, defaults to `REPO_WITH_BINARIES_USERNAME`. If that's not set defaults to `admin`. +- `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_PASSWORD` - (optional) password if the `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL` +requires authentication, defaults to `REPO_WITH_BINARIES_PASSWORD`. If that's not set defaults to `password`. +- `EXTERNAL_CONTRACTS_PATH` - path to contracts for the given project, inside the project with contracts. +Defaults to slash separated `EXTERNAL_CONTRACTS_GROUP_ID` concatenated with `/` and `EXTERNAL_CONTRACTS_ARTIFACT_ID`. E.g. +for group id `foo.bar` and artifact id `baz`, would result in `foo/bar/baz` contracts path. +- `EXTERNAL_CONTRACTS_WORK_OFFLINE` - if set to `true` then will retrieve artifact with contracts +from the container's `.m2`. Mount your local `.m2` as a volume available at the container's `/root/.m2` path. +You must not set both `EXTERNAL_CONTRACTS_WORK_OFFLINE` and `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL`. + + +These environment variables are used when tests are executed: + +- `APPLICATION_BASE_URL` - url against which tests should be executed. +Remember that it has to be accessible from the Docker container (e.g. `localhost` +will not work) +- `APPLICATION_USERNAME` - (optional) username for basic authentication to your application +- `APPLICATION_PASSWORD` - (optional) password for basic authentication to your application + +== Example of usage + +Let's take a look at a simple MVC application + +```bash +$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs +$ cd bookstore +``` + +The contracts are available under `/contracts` folder. + +[[docker-server-side]] +== Server side (nodejs) + +Since we want to run tests, we could just execute: + +```bash +$ npm test +``` + +however, for learning purposes, let's split it into pieces: + +```bash +# Stop docker infra (nodejs, artifactory) +$ ./stop_infra.sh +# Start docker infra (nodejs, artifactory) +$ ./setup_infra.sh + +# Kill & Run app +$ pkill -f "node app" +$ nohup node app & + +# Prepare environment variables +$ SC_CONTRACT_DOCKER_VERSION="..." +$ APP_IP="192.168.0.100" +$ APP_PORT="3000" +$ ARTIFACTORY_PORT="8081" +$ APPLICATION_BASE_URL="http://${APP_IP}:${APP_PORT}" +$ ARTIFACTORY_URL="http://${APP_IP}:${ARTIFACTORY_PORT}/artifactory/libs-release-local" +$ CURRENT_DIR="$( pwd )" +$ CURRENT_FOLDER_NAME=${PWD##*/} +$ PROJECT_VERSION="0.0.1.RELEASE" + +# Execute contract tests +$ docker run --rm -e "APPLICATION_BASE_URL=${APPLICATION_BASE_URL}" -e "PUBLISH_ARTIFACTS=true" -e "PROJECT_NAME=${CURRENT_FOLDER_NAME}" -e "REPO_WITH_BINARIES_URL=${ARTIFACTORY_URL}" -e "PROJECT_VERSION=${PROJECT_VERSION}" -v "${CURRENT_DIR}/contracts/:/contracts:ro" -v "${CURRENT_DIR}/node_modules/spring-cloud-contract/output:/spring-cloud-contract-output/" springcloud/spring-cloud-contract:"${SC_CONTRACT_DOCKER_VERSION}" + +# Kill app +$ pkill -f "node app" +``` + +What will happen is that via bash scripts: + +- infrastructure will be set up (MongoDb, Artifactory). +In real life scenario you would just run the NodeJS application +with mocked database. In this example we want to show how we can +benefit from Spring Cloud Contract in no time. +- due to those constraints the contracts also represent the +stateful situation +** first request is a `POST` that causes data to get inserted to the database +** second request is a `GET` that returns a list of data with 1 previously inserted element +- the NodeJS application will be started (on port `3000`) +- contract tests will be generated via Docker and tests +will be executed against the running application +** the contracts will be taken from `/contracts` folder. +** the output of the test execution is available under +`node_modules/spring-cloud-contract/output`. +- the stubs will be uploaded to Artifactory. You can check them out +under http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/ . +The stubs will be here http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/bookstore-0.0.1.RELEASE-stubs.jar. + +To see how the client side looks like check out the <> section. diff --git a/docs/src/main/asciidoc/gradle-project.adoc b/docs/src/main/asciidoc/gradle-project.adoc new file mode 100644 index 0000000000..8d03c5b3e8 --- /dev/null +++ b/docs/src/main/asciidoc/gradle-project.adoc @@ -0,0 +1,420 @@ +:branch: master +:core_path: ../../.. +:plugins_path: ../../../spring-cloud-contract-tools +:converters_path: {plugins_path}/spring-cloud-contract-converters +: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 +:samples_path: {core_path}/samples +:verifier_core_path: {verifier_root_path} +:stubrunner_core_path: {core_path}/spring-cloud-contract-stub-runner +:standalone_samples_path: {samples_path}/standalone/dsl +:standalone_messaging_samples_path: {samples_path}/standalone/messaging +:standalone_pact_path: {samples_path}/standalone/pact +:standalone_restdocs_path: {samples_path}/standalone/restdocs +:tests_path: {core_path}/tests +:samples_branch: 2.2.x +:samples_url: https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-contract-samples/{samples_branch} +:introduction_url: ${core_path}/../../ + += Gradle Project + +To learn how to set up the Gradle project for Spring Cloud Contract Verifier, read the +following sections: + +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> + +[[gradle-prerequisites]] +== Prerequisites + +In order to use Spring Cloud Contract Verifier with WireMock, you muse use either a +Gradle or a Maven plugin. + +WARNING: If you want to use Spock in your projects, you must add separately the +`spock-core` and `spock-spring` modules. Check https://spockframework.github.io/[Spock +docs for more information] + +[[gradle-add-gradle-plugin]] +== Add Gradle Plugin with Dependencies + +To add a Gradle plugin with dependencies, use code similar to this: + +[source,groovy,indent=0] +---- +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springboot_version}" + classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifier_version}" + } +} + +apply plugin: 'groovy' +apply plugin: 'spring-cloud-contract' + +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${verifier_version}" + } +} + +dependencies { + testCompile 'org.codehaus.groovy:groovy-all:2.4.6' + // example with adding Spock core and Spock Spring + testCompile 'org.spockframework:spock-core:1.0-groovy-2.4' + testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4' + testCompile 'org.springframework.cloud:spring-cloud-starter-contract-verifier' +} +---- + +[[gradle-and-rest-assured]] +== Gradle and Rest Assured 2.0 + +By default, Rest Assured 3.x is added to the classpath. However, to use Rest Assured 2.x +you can add it to the plugins classpath, as shown here: + +[source,groovy,indent=0] +---- +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springboot_version}" + classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifier_version}" + classpath "com.jayway.restassured:rest-assured:2.5.0" + classpath "com.jayway.restassured:spring-mock-mvc:2.5.0" + } +} + +depenendencies { + // all dependencies + // you can exclude rest-assured from spring-cloud-contract-verifier + testCompile "com.jayway.restassured:rest-assured:2.5.0" + testCompile "com.jayway.restassured:spring-mock-mvc:2.5.0" +} +---- + +That way, the plugin automatically sees that Rest Assured 2.x is present on the classpath +and modifies the imports accordingly. + +[[gradle-snapshot-versions]] +== Snapshot Versions for Gradle + +Add the additional snapshot repository to your build.gradle to use snapshot versions, +which are automatically uploaded after every successful build, as shown here: + +[source,groovy,indent=0] +---- +include::{standalone_samples_path}/http-server/build.gradle[tags=repos,indent=0] +} +---- +[[gradle-add-stubs]] +== Add stubs + +By default, Spring Cloud Contract Verifier is looking for stubs in the +`src/test/resources/contracts` directory. + +The directory containing stub definitions is treated as a class name, and each stub +definition is treated as a single test. Spring Cloud Contract Verifier assumes that it +contains at least one level of directories that are to be used as the test class name. +If more than one level of nested directories is present, all except the last one is used +as the package name. For example, with following structure: + +[source,groovy,indent=0] +---- +src/test/resources/contracts/myservice/shouldCreateUser.groovy +src/test/resources/contracts/myservice/shouldReturnUser.groovy +---- + +Spring Cloud Contract Verifier creates a test class named `defaultBasePackage.MyService` +with two methods: + + - `shouldCreateUser()` + - `shouldReturnUser()` + +[[gradle-run-plugin]] +== Run the Plugin + +The plugin registers itself to be invoked before a `check` task. If you want it to be +part of your build process, you need to do nothing more. If you just want to generate +tests, invoke the `generateContractTests` task. + +[[gradle-default-setup]] +== Default Setup + +The default Gradle Plugin setup creates the following Gradle part of the build (in +pseudocode): + +[source,groovy,indent=0] +---- +contracts { + testFramework ='JUNIT' + testMode = 'MockMvc' + generatedTestSourcesDir = project.file("${project.buildDir}/generated-test-sources/contracts") + generatedTestResourcesDir = project.file("${project.buildDir}/generated-test-resources/contracts") + contractsDslDir = "${project.rootDir}/src/test/resources/contracts" + basePackageForTests = 'org.springframework.cloud.verifier.tests' + stubsOutputDir = project.file("${project.buildDir}/stubs") + + // the following properties are used when you want to provide where the JAR with contract lays + contractDependency { + stringNotation = '' + } + contractsPath = '' + contractsWorkOffline = false + contractRepository { + cacheDownloadedContracts(true) + } +} + +tasks.create(type: Jar, name: 'verifierStubsJar', dependsOn: 'generateClientStubs') { + baseName = project.name + classifier = contracts.stubsSuffix + from contractVerifier.stubsOutputDir +} + +project.artifacts { + archives task +} + +tasks.create(type: Copy, name: 'copyContracts') { + from contracts.contractsDslDir + into contracts.stubsOutputDir +} + +verifierStubsJar.dependsOn 'copyContracts' + +publishing { + publications { + stubs(MavenPublication) { + artifactId project.name + artifact verifierStubsJar + } + } +} +---- + +[[gradle-configure-plugin]] +== Configure Plugin + +To change the default configuration, add a `contracts` snippet to your Gradle config, as +shown here: + +[source,groovy,indent=0] +---- +contracts { + testMode = 'MockMvc' + baseClassForTests = 'org.mycompany.tests' + generatedTestSourcesDir = project.file('src/generatedContract') +} +---- + +[[gradle-configuration-options]] +== Configuration Options + +* *testMode*: Defines the mode for acceptance tests. By default, the mode is MockMvc, +which is based on Spring's MockMvc. It can also be changed to *WebTestClient*, *JaxRsClient* or to +*Explicit* for real HTTP calls. +* *imports*: Creates an array with imports that should be included in generated tests +(for example ['org.myorg.Matchers']). By default, it creates an empty array. +* *staticImports*: Creates an array with static imports that should be included in +generated tests(for example ['org.myorg.Matchers.*']). By default, it creates an empty +array. +* *basePackageForTests*: Specifies the base package for all generated tests. If not set, +the value is picked from `baseClassForTests`'s package and from `packageWithBaseClasses`. +If neither of these values are set, then the value is set to +`org.springframework.cloud.contract.verifier.tests`. +* *baseClassForTests*: Creates a base class for all generated tests. By default, if you +use Spock classes, the class is `spock.lang.Specification`. +* *packageWithBaseClasses*: Defines a package where all the base classes reside. This +setting takes precedence over *baseClassForTests*. +* *baseClassMappings*: Explicitly maps a contract package to a FQN of a base class. This +setting takes precedence over *packageWithBaseClasses* and *baseClassForTests*. +* *ruleClassForTests*: Specifies a rule that should be added to the generated test +classes. +* *ignoredFiles*: Uses an `Antmatcher` to allow defining stub files for which processing +should be skipped. By default, it is an empty array. +* *contractsDslDir*: Specifies the directory containing contracts written using the +GroovyDSL. By default, its value is `$rootDir/src/test/resources/contracts`. +* *generatedTestSourcesDir*: Specifies the test source directory where tests generated +from the Groovy DSL should be placed. By default its value is +`$buildDir/generated-test-sources/contracts`. +* *generatedTestResourcesDir*: Specifies the test resource directory where resources used by the tests generated +from the Groovy DSL should be placed. By default its value is +`$buildDir/generated-test-resources/contracts`. +* *stubsOutputDir*: Specifies the directory where the generated WireMock stubs from +the Groovy DSL should be placed. +* *testFramework*: Specifies the target test framework to be used. Currently, Spock, JUnit 4 (`TestFramework.JUNIT`) and +JUnit 5 are supported with JUnit 4 being the default framework. +* *contractsProperties*: a map containing properties to be passed to Spring Cloud Contract +components. Those properties might be used by e.g. inbuilt or custom Stub Downloaders. + +The following properties are used when you want to specify the location of the JAR +containing the contracts: + +* *contractDependency*: Specifies the Dependency that provides +`groupid:artifactid:version:classifier` coordinates. You can use the `contractDependency` +closure to set it up. +* *contractsPath*: Specifies the path to the jar. If contract dependencies are + downloaded, the path defaults to `groupid/artifactid` where `groupid` is slash + separated. Otherwise, it scans contracts under the provided directory. +* *contractsMode*: Specifies the mode of downloading contracts (whether the +JAR is available offline, remotely etc.) +* *deleteStubsAfterTest*: If set to `false` will not remove any downloaded +contracts from temporary directories + +Below you can find a list of experimental features you can turn on via the plugin: + +* *convertToYaml*: converts all DSLs to the declarative, YAML format. This can be extremely useful when you're using external libraries in your Groovy DSLs. By turning this feature on (by setting it to `true`) you will not need to add the library dependency on the consumer side. +* *assertJsonSize*: You can check the size of JSON arrays in the generated tests. This feature is disabled by default. + +[[gradle-single-base-class]] +== Single Base Class for All Tests + +When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base +specification for all generated acceptance tests. In this class, you need to point to an +endpoint, which should be verified. + +[source,groovy,indent=0] +---- +include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/org/springframework/cloud/contract/verifier/twitter/places/BaseMockMvcSpec.groovy[tags=base_class,indent=0] +---- + +If you use `Explicit` mode, you can use a base class to initialize the whole tested app +as you might see in regular integration tests. If you use the `JAXRSCLIENT` mode, this +base class should also contain a `protected WebTarget webTarget` field. Right now, the +only option to test the JAX-RS API is to start a web server. + +[[gradle-different-base-classes]] +== Different Base Classes for Contracts + +If your base classes differ between contracts, you can tell the Spring Cloud Contract +plugin which class should get extended by the autogenerated tests. You have two options: + +* Follow a convention by providing the `packageWithBaseClasses` +* Provide explicit mapping via `baseClassMappings` + +*By Convention* + +The convention is such that if you have a contract under (for example) +`src/test/resources/contract/foo/bar/baz/` and set the value of the +`packageWithBaseClasses` property to `com.example.base`, then Spring Cloud Contract +Verifier assumes that there is a `BarBazBase` class under the `com.example.base` package. +In other words, the system takes the last two parts of the package, if they exist, and +forms a class with a `Base` suffix. This rule takes precedence over *baseClassForTests*. +Here is an example of how it works in the `contracts` closure: + +[source,groovy,indent=0] +---- +include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierSpec.groovy[tags=package_with_base_classes,indent=0] +---- + +*By Mapping* + +You can manually map a regular expression of the contract's package to fully qualified +name of the base class for the matched contract. You have to provide a list called +`baseClassMappings` that consists `baseClassMapping` objects that takes a +`contractPackageRegex` to `baseClassFQN` mapping. Consider the following example: + +[source,groovy,indent=0] +---- +include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierSpec.groovy[tags=base_class_mappings,indent=0] +---- + +Let's assume that you have contracts under + - `src/test/resources/contract/com/` + - `src/test/resources/contract/foo/` + +By providing the `baseClassForTests`, we have a fallback in case mapping did not succeed. +(You could also provide the `packageWithBaseClasses` as a fallback.) That way, the tests +generated from `src/test/resources/contract/com/` contracts extend the +`com.example.ComBase`, whereas the rest of the tests extend `com.example.FooBase`. + +[[gradle-invoking-generated-tests]] +== Invoking Generated Tests + +To ensure that the provider side is compliant with defined contracts, you need to invoke: + +[source,bash,indent=0] +---- +./gradlew generateContractTests test +---- + +[[gradle-pushing-stubs-to-scm]] +== Pushing stubs to SCM + +If you're using the SCM repository to keep the contracts and +stubs, you might want to automate the step of pushing stubs to +the repository. To do that, it's enough to call the `pushStubsToScm` +task. Example: + +[source,bash,indent=0] +---- +$ ./gradlew pushStubsToScm +---- + +Under <> you can find all possible +configuration options that you can pass either via +the `contractsProperties` field e.g. `contracts { contractsProperties = [foo:"bar"] }`, +via `contractsProperties` method e.g. `contracts { contractsProperties([foo:"bar"]) }`, +a system property or an environment variable. + +[[gradle-consumer]] +== Spring Cloud Contract Verifier on the Consumer Side + +In a consuming service, you need to configure the Spring Cloud Contract Verifier plugin +in exactly the same way as in case of provider. If you do not want to use Stub Runner +then you need to copy contracts stored in `src/test/resources/contracts` and generate +WireMock JSON stubs using: + +[source,bash,indent=0] +---- +./gradlew generateClientStubs +---- + +NOTE: The `stubsOutputDir` option has to be set for stub generation to work. + +When present, JSON stubs can be used in automated tests of consuming a service. + +[source,groovy,indent=0] +---- +@ContextConfiguration(loader == SpringApplicationContextLoader, classes == Application) +class LoanApplicationServiceSpec extends Specification { + + @ClassRule + @Shared + WireMockClassRule wireMockRule == new WireMockClassRule() + + @Autowired + LoanApplicationService sut + + def 'should successfully apply for loan'() { + given: + LoanApplication application = + new LoanApplication(client: new Client(clientPesel: '12345678901'), amount: 123.123) + when: + LoanApplicationResult loanApplication == sut.loanApplication(application) + then: + loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLIED + loanApplication.rejectionReason == null + } +} +---- + +`LoanApplication` makes a call to `FraudDetection` service. This request is handled by a +WireMock server configured with stubs generated by Spring Cloud Contract Verifier. \ No newline at end of file diff --git a/docs/src/main/asciidoc/verifier_setup.adoc b/docs/src/main/asciidoc/maven-project.adoc similarity index 66% rename from docs/src/main/asciidoc/verifier_setup.adoc rename to docs/src/main/asciidoc/maven-project.adoc index 24c4a7a32e..2cb981a6e9 100644 --- a/docs/src/main/asciidoc/verifier_setup.adoc +++ b/docs/src/main/asciidoc/maven-project.adoc @@ -1,416 +1,23 @@ -== Spring Cloud Contract Verifier Setup - -You can set up Spring Cloud Contract Verifier in the following ways: - -* <> -* <> -* <> - -[[gradle-project]] -=== Gradle Project - -To learn how to set up the Gradle project for Spring Cloud Contract Verifier, read the -following sections: - -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> -* <> - -[[gradle-prerequisites]] -==== Prerequisites - -In order to use Spring Cloud Contract Verifier with WireMock, you muse use either a -Gradle or a Maven plugin. - -WARNING: If you want to use Spock in your projects, you must add separately the -`spock-core` and `spock-spring` modules. Check https://spockframework.github.io/[Spock -docs for more information] - -[[gradle-add-gradle-plugin]] -==== Add Gradle Plugin with Dependencies - -To add a Gradle plugin with dependencies, use code similar to this: - -[source,groovy,indent=0] ----- -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath "org.springframework.boot:spring-boot-gradle-plugin:${springboot_version}" - classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifier_version}" - } -} - -apply plugin: 'groovy' -apply plugin: 'spring-cloud-contract' - -dependencyManagement { - imports { - mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:${verifier_version}" - } -} - -dependencies { - testCompile 'org.codehaus.groovy:groovy-all:2.4.6' - // example with adding Spock core and Spock Spring - testCompile 'org.spockframework:spock-core:1.0-groovy-2.4' - testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4' - testCompile 'org.springframework.cloud:spring-cloud-starter-contract-verifier' -} ----- - -[[gradle-and-rest-assured]] -==== Gradle and Rest Assured 2.0 - -By default, Rest Assured 3.x is added to the classpath. However, to use Rest Assured 2.x -you can add it to the plugins classpath, as shown here: - -[source,groovy,indent=0] ----- -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath "org.springframework.boot:spring-boot-gradle-plugin:${springboot_version}" - classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifier_version}" - classpath "com.jayway.restassured:rest-assured:2.5.0" - classpath "com.jayway.restassured:spring-mock-mvc:2.5.0" - } -} - -depenendencies { - // all dependencies - // you can exclude rest-assured from spring-cloud-contract-verifier - testCompile "com.jayway.restassured:rest-assured:2.5.0" - testCompile "com.jayway.restassured:spring-mock-mvc:2.5.0" -} ----- - -That way, the plugin automatically sees that Rest Assured 2.x is present on the classpath -and modifies the imports accordingly. - -[[gradle-snapshot-versions]] -==== Snapshot Versions for Gradle - -Add the additional snapshot repository to your build.gradle to use snapshot versions, -which are automatically uploaded after every successful build, as shown here: - -[source,groovy,indent=0] ----- -include::{standalone_samples_path}/http-server/build.gradle[tags=repos,indent=0] -} ----- -[[gradle-add-stubs]] -==== Add stubs - -By default, Spring Cloud Contract Verifier is looking for stubs in the -`src/test/resources/contracts` directory. - -The directory containing stub definitions is treated as a class name, and each stub -definition is treated as a single test. Spring Cloud Contract Verifier assumes that it -contains at least one level of directories that are to be used as the test class name. -If more than one level of nested directories is present, all except the last one is used -as the package name. For example, with following structure: - -[source,groovy,indent=0] ----- -src/test/resources/contracts/myservice/shouldCreateUser.groovy -src/test/resources/contracts/myservice/shouldReturnUser.groovy ----- - -Spring Cloud Contract Verifier creates a test class named `defaultBasePackage.MyService` -with two methods: - - - `shouldCreateUser()` - - `shouldReturnUser()` - -[[gradle-run-plugin]] -==== Run the Plugin - -The plugin registers itself to be invoked before a `check` task. If you want it to be -part of your build process, you need to do nothing more. If you just want to generate -tests, invoke the `generateContractTests` task. - -[[gradle-default-setup]] -==== Default Setup - -The default Gradle Plugin setup creates the following Gradle part of the build (in -pseudocode): - -[source,groovy,indent=0] ----- -contracts { - testFramework ='JUNIT' - testMode = 'MockMvc' - generatedTestSourcesDir = project.file("${project.buildDir}/generated-test-sources/contracts") - generatedTestResourcesDir = project.file("${project.buildDir}/generated-test-resources/contracts") - contractsDslDir = "${project.rootDir}/src/test/resources/contracts" - basePackageForTests = 'org.springframework.cloud.verifier.tests' - stubsOutputDir = project.file("${project.buildDir}/stubs") - - // the following properties are used when you want to provide where the JAR with contract lays - contractDependency { - stringNotation = '' - } - contractsPath = '' - contractsWorkOffline = false - contractRepository { - cacheDownloadedContracts(true) - } -} - -tasks.create(type: Jar, name: 'verifierStubsJar', dependsOn: 'generateClientStubs') { - baseName = project.name - classifier = contracts.stubsSuffix - from contractVerifier.stubsOutputDir -} - -project.artifacts { - archives task -} - -tasks.create(type: Copy, name: 'copyContracts') { - from contracts.contractsDslDir - into contracts.stubsOutputDir -} - -verifierStubsJar.dependsOn 'copyContracts' - -publishing { - publications { - stubs(MavenPublication) { - artifactId project.name - artifact verifierStubsJar - } - } -} ----- - -[[gradle-configure-plugin]] -==== Configure Plugin - -To change the default configuration, add a `contracts` snippet to your Gradle config, as -shown here: - -[source,groovy,indent=0] ----- -contracts { - testMode = 'MockMvc' - baseClassForTests = 'org.mycompany.tests' - generatedTestSourcesDir = project.file('src/generatedContract') -} ----- - -[[gradle-configuration-options]] -==== Configuration Options - -* *testMode*: Defines the mode for acceptance tests. By default, the mode is MockMvc, -which is based on Spring's MockMvc. It can also be changed to *WebTestClient*, *JaxRsClient* or to -*Explicit* for real HTTP calls. -* *imports*: Creates an array with imports that should be included in generated tests -(for example ['org.myorg.Matchers']). By default, it creates an empty array. -* *staticImports*: Creates an array with static imports that should be included in -generated tests(for example ['org.myorg.Matchers.*']). By default, it creates an empty -array. -* *basePackageForTests*: Specifies the base package for all generated tests. If not set, -the value is picked from `baseClassForTests`'s package and from `packageWithBaseClasses`. -If neither of these values are set, then the value is set to -`org.springframework.cloud.contract.verifier.tests`. -* *baseClassForTests*: Creates a base class for all generated tests. By default, if you -use Spock classes, the class is `spock.lang.Specification`. -* *packageWithBaseClasses*: Defines a package where all the base classes reside. This -setting takes precedence over *baseClassForTests*. -* *baseClassMappings*: Explicitly maps a contract package to a FQN of a base class. This -setting takes precedence over *packageWithBaseClasses* and *baseClassForTests*. -* *ruleClassForTests*: Specifies a rule that should be added to the generated test -classes. -* *ignoredFiles*: Uses an `Antmatcher` to allow defining stub files for which processing -should be skipped. By default, it is an empty array. -* *contractsDslDir*: Specifies the directory containing contracts written using the -GroovyDSL. By default, its value is `$rootDir/src/test/resources/contracts`. -* *generatedTestSourcesDir*: Specifies the test source directory where tests generated -from the Groovy DSL should be placed. By default its value is -`$buildDir/generated-test-sources/contracts`. -* *generatedTestResourcesDir*: Specifies the test resource directory where resources used by the tests generated -from the Groovy DSL should be placed. By default its value is -`$buildDir/generated-test-resources/contracts`. -* *stubsOutputDir*: Specifies the directory where the generated WireMock stubs from -the Groovy DSL should be placed. -* *testFramework*: Specifies the target test framework to be used. Currently, Spock, JUnit 4 (`TestFramework.JUNIT`) and -JUnit 5 are supported with JUnit 4 being the default framework. -* *contractsProperties*: a map containing properties to be passed to Spring Cloud Contract -components. Those properties might be used by e.g. inbuilt or custom Stub Downloaders. - -The following properties are used when you want to specify the location of the JAR -containing the contracts: - -* *contractDependency*: Specifies the Dependency that provides -`groupid:artifactid:version:classifier` coordinates. You can use the `contractDependency` -closure to set it up. -* *contractsPath*: Specifies the path to the jar. If contract dependencies are - downloaded, the path defaults to `groupid/artifactid` where `groupid` is slash - separated. Otherwise, it scans contracts under the provided directory. -* *contractsMode*: Specifies the mode of downloading contracts (whether the -JAR is available offline, remotely etc.) -* *deleteStubsAfterTest*: If set to `false` will not remove any downloaded -contracts from temporary directories - -Below you can find a list of experimental features you can turn on via the plugin: - -* *convertToYaml*: converts all DSLs to the declarative, YAML format. This can be extremely useful when you're using external libraries in your Groovy DSLs. By turning this feature on (by setting it to `true`) you will not need to add the library dependency on the consumer side. -* *assertJsonSize*: You can check the size of JSON arrays in the generated tests. This feature is disabled by default. - -[[gradle-single-base-class]] -==== Single Base Class for All Tests - -When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base -specification for all generated acceptance tests. In this class, you need to point to an -endpoint, which should be verified. - -[source,groovy,indent=0] ----- -include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/org/springframework/cloud/contract/verifier/twitter/places/BaseMockMvcSpec.groovy[tags=base_class,indent=0] ----- - -If you use `Explicit` mode, you can use a base class to initialize the whole tested app -as you might see in regular integration tests. If you use the `JAXRSCLIENT` mode, this -base class should also contain a `protected WebTarget webTarget` field. Right now, the -only option to test the JAX-RS API is to start a web server. - -[[gradle-different-base-classes]] -==== Different Base Classes for Contracts - -If your base classes differ between contracts, you can tell the Spring Cloud Contract -plugin which class should get extended by the autogenerated tests. You have two options: - -* Follow a convention by providing the `packageWithBaseClasses` -* Provide explicit mapping via `baseClassMappings` - -*By Convention* - -The convention is such that if you have a contract under (for example) -`src/test/resources/contract/foo/bar/baz/` and set the value of the -`packageWithBaseClasses` property to `com.example.base`, then Spring Cloud Contract -Verifier assumes that there is a `BarBazBase` class under the `com.example.base` package. -In other words, the system takes the last two parts of the package, if they exist, and -forms a class with a `Base` suffix. This rule takes precedence over *baseClassForTests*. -Here is an example of how it works in the `contracts` closure: - -[source,groovy,indent=0] ----- -include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierSpec.groovy[tags=package_with_base_classes,indent=0] ----- - -*By Mapping* - -You can manually map a regular expression of the contract's package to fully qualified -name of the base class for the matched contract. You have to provide a list called -`baseClassMappings` that consists `baseClassMapping` objects that takes a -`contractPackageRegex` to `baseClassFQN` mapping. Consider the following example: - -[source,groovy,indent=0] ----- -include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierSpec.groovy[tags=base_class_mappings,indent=0] ----- - -Let's assume that you have contracts under - - `src/test/resources/contract/com/` - - `src/test/resources/contract/foo/` - -By providing the `baseClassForTests`, we have a fallback in case mapping did not succeed. -(You could also provide the `packageWithBaseClasses` as a fallback.) That way, the tests -generated from `src/test/resources/contract/com/` contracts extend the -`com.example.ComBase`, whereas the rest of the tests extend `com.example.FooBase`. - -[[gradle-invoking-generated-tests]] -==== Invoking Generated Tests - -To ensure that the provider side is compliant with defined contracts, you need to invoke: - -[source,bash,indent=0] ----- -./gradlew generateContractTests test ----- - -[[gradle-pushing-stubs-to-scm]] -==== Pushing stubs to SCM - -If you're using the SCM repository to keep the contracts and -stubs, you might want to automate the step of pushing stubs to -the repository. To do that, it's enough to call the `pushStubsToScm` -task. Example: - -[source,bash,indent=0] ----- -$ ./gradlew pushStubsToScm ----- - -Under <> you can find all possible -configuration options that you can pass either via -the `contractsProperties` field e.g. `contracts { contractsProperties = [foo:"bar"] }`, -via `contractsProperties` method e.g. `contracts { contractsProperties([foo:"bar"]) }`, -a system property or an environment variable. - -[[gradle-consumer]] -==== Spring Cloud Contract Verifier on the Consumer Side - -In a consuming service, you need to configure the Spring Cloud Contract Verifier plugin -in exactly the same way as in case of provider. If you do not want to use Stub Runner -then you need to copy contracts stored in `src/test/resources/contracts` and generate -WireMock JSON stubs using: - -[source,bash,indent=0] ----- -./gradlew generateClientStubs ----- - -NOTE: The `stubsOutputDir` option has to be set for stub generation to work. - -When present, JSON stubs can be used in automated tests of consuming a service. - -[source,groovy,indent=0] ----- -@ContextConfiguration(loader == SpringApplicationContextLoader, classes == Application) -class LoanApplicationServiceSpec extends Specification { - - @ClassRule - @Shared - WireMockClassRule wireMockRule == new WireMockClassRule() - - @Autowired - LoanApplicationService sut - - def 'should successfully apply for loan'() { - given: - LoanApplication application = - new LoanApplication(client: new Client(clientPesel: '12345678901'), amount: 123.123) - when: - LoanApplicationResult loanApplication == sut.loanApplication(application) - then: - loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLIED - loanApplication.rejectionReason == null - } -} ----- - -`LoanApplication` makes a call to `FraudDetection` service. This request is handled by a -WireMock server configured with stubs generated by Spring Cloud Contract Verifier. - -[[maven-project]] -=== Maven Project +:branch: master +:core_path: ../../.. +:plugins_path: ../../../spring-cloud-contract-tools +:converters_path: {plugins_path}/spring-cloud-contract-converters +: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 +:samples_path: {core_path}/samples +:verifier_core_path: {verifier_root_path} +:stubrunner_core_path: {core_path}/spring-cloud-contract-stub-runner +:standalone_samples_path: {samples_path}/standalone/dsl +:standalone_messaging_samples_path: {samples_path}/standalone/messaging +:standalone_pact_path: {samples_path}/standalone/pact +:standalone_restdocs_path: {samples_path}/standalone/restdocs +:tests_path: {core_path}/tests +:samples_branch: 2.2.x +:samples_url: https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-contract-samples/{samples_branch} +:introduction_url: ${core_path}/../../ + += Maven Project To learn how to set up the Maven project for Spring Cloud Contract Verifier, read the following sections: @@ -429,7 +36,7 @@ following sections: * <> [[maven-add-plugin]] -==== Add maven plugin +== Add maven plugin Add the Spring Cloud Contract BOM in a fashion similar to this: @@ -450,7 +57,7 @@ https://cloud.spring.io/spring-cloud-static/spring-cloud-contract/2.0.0.RELEASE/ Cloud Contract Maven Plugin Documentation (example for `2.0.0.RELEASE` version)]. [[maven-rest-assured]] -==== Maven and Rest Assured 2.0 +== Maven and Rest Assured 2.0 By default, Rest Assured 3.x is added to the classpath. However, you can use Rest Assured 2.x by adding it to the plugins classpath, as shown here: @@ -508,7 +115,7 @@ That way, the plugin automatically sees that Rest Assured 3.x is present on the and modifies the imports accordingly. [[maven-snapshot-versions]] -==== Snapshot versions for Maven +== Snapshot versions for Maven For Snapshot and Milestone versions, you have to add the following section to your `pom.xml`, as shown here: @@ -519,7 +126,7 @@ include::{standalone_samples_path}/http-server/pom.xml[tags=repos,indent=0] ---- [[maven-add-stubs]] -==== Add stubs +== Add stubs By default, Spring Cloud Contract Verifier is looking for stubs in the `src/test/resources/contracts` directory. The directory containing stub definitions is @@ -541,14 +148,14 @@ with two methods * `shouldReturnUser()` [[maven-run-plugin]] -==== Run plugin +== Run plugin The plugin goal `generateTests` is assigned to be invoked in the phase called `generate-test-sources`. If you want it to be part of your build process, you need not do anything. If you just want to generate tests, invoke the `generateTests` goal. [[maven-configure-plugin]] -==== Configure plugin +== Configure plugin To change the default configuration, just add a `configuration` section to the plugin definition or the `execution` definition, as shown here: @@ -575,7 +182,7 @@ definition or the `execution` definition, as shown here: ---- [[maven-configuration-options]] -==== Configuration Options +== Configuration Options * *testMode*: Defines the mode for acceptance tests. By default, the mode is MockMvc, which is based on Spring's MockMvc. It can also be changed to *WebTestClient*, *JaxRsClient* or to @@ -639,7 +246,7 @@ Below you can find a list of experimental features you can turn on via the plugi * *assertJsonSize*: You can check the size of JSON arrays in the generated tests. This feature is disabled by default. [[maven-single-base]] -==== Single Base Class for All Tests +== Single Base Class for All Tests When using Spring Cloud Contract Verifier in default MockMvc, you need to create a base specification for all generated acceptance tests. In this class, you need to point to an @@ -718,7 +325,7 @@ If you use the `JAXRSCLIENT` mode, this base class should also contain a `protec now, the only option to test the JAX-RS API is to start a web server. [[maven-different-base]] -==== Different base classes for contracts +== Different base classes for contracts If your base classes differ between contracts, you can tell the Spring Cloud Contract plugin which class should get extended by the autogenerated tests. You have two options: @@ -763,7 +370,7 @@ generated from `src/test/resources/contract/com/` contracts extend the `com.example.ComBase`, whereas the rest of the tests extend `com.example.FooBase`. [[maven-invoking-generated-tests]] -==== Invoking generated tests +== Invoking generated tests The Spring Cloud Contract Maven Plugin generates verification code in a directory called `/generated-test-sources/contractVerifier` and attaches this directory to `testCompile` @@ -807,7 +414,7 @@ To ensure that provider side is compliant with defined contracts, you need to in `mvn generateTest test`. [[maven-pushing-stubs-to-scm]] -==== Pushing stubs to SCM +== Pushing stubs to SCM If you're using the SCM repository to keep the contracts and stubs, you might want to automate the step of pushing stubs to @@ -858,7 +465,7 @@ the `` map, a system property or an environment variable. [[maven-sts]] -==== Maven Plugin and STS +== Maven Plugin and STS If you see the following exception while using STS: @@ -915,7 +522,7 @@ In order to fix this issue, provide the following section in your `pom.xml`: ---- -==== Maven Plugin with Spock Tests +== Maven Plugin with Spock Tests You can select the http://spockframework.org/[Spock Framework] for creating and executing the auto-generated contract verification tests with both Maven and Gradle plugin. However, whereas with Gradle its really straightforward, @@ -939,7 +546,7 @@ Surefire plugin setup, like in the following example: include::{samples_url}/producer_with_spock/pom.xml[tags=pock-surefire-setup,indent=0] ---- -=== Stubs and Transitive Dependencies += Stubs and Transitive Dependencies The Maven and Gradle plugin that add the tasks that create the stubs jar for you. One problem that arises is that, when reusing the stubs, you can mistakenly import all of @@ -983,7 +590,7 @@ For example, you might decide to have no dependencies at all. As a consumer, if you add the stub dependency to your classpath, you can explicitly exclude the unwanted dependencies. -=== Scenarios += Scenarios 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 @@ -1012,7 +619,7 @@ https://wiremock.org/docs/stateful-behaviour/[https://wiremock.org/docs/stateful Spring Cloud Contract Verifier also generates tests with a guaranteed order of execution. [[docker-project]] -=== Docker Project += Docker Project We're publishing a `springcloud/spring-cloud-contract` Docker image that contains a project that will generate tests and execute them in `EXPLICIT` mode @@ -1021,7 +628,7 @@ against a running application. TIP: The `EXPLICIT` mode means that the tests generated from contracts will send real requests and not the mocked ones. -==== Short intro to Maven, JARs and Binary storage +== Short intro to Maven, JARs and Binary storage Since the Docker image can be used by non JVM projects, it's good to explain the basic terms behind Spring Cloud Contract packaging defaults. @@ -1061,7 +668,7 @@ and for Docker those would be Docker images. You can store those artifacts in a manager. Examples of such managers can be https://jfrog.com/artifactory/[Artifactory] or https://www.sonatype.org/nexus/[Nexus]. -==== How it works +== How it works The image searches for contracts under the `/contracts` folder. The output from running the tests will be available under @@ -1076,7 +683,7 @@ It's enough for you to mount your contracts, pass the environment variables - generate the https://github.com/tomakehurst/wiremock[WireMock] stubs - (optional - turned on by default) publish the stubs to a Artifact Manager -===== Environment Variables +=== Environment Variables The Docker image requires some environment variables to point to your running application, to the Artifact manager instance etc. @@ -1121,7 +728,7 @@ will not work) - `APPLICATION_USERNAME` - (optional) username for basic authentication to your application - `APPLICATION_PASSWORD` - (optional) password for basic authentication to your application -==== Example of usage +== Example of usage Let's take a look at a simple MVC application @@ -1133,7 +740,7 @@ $ cd bookstore The contracts are available under `/contracts` folder. [[docker-server-side]] -==== Server side (nodejs) +== Server side (nodejs) Since we want to run tests, we could just execute: diff --git a/docs/src/main/asciidoc/migrations.adoc b/docs/src/main/asciidoc/migrations.adoc deleted file mode 100644 index b4c8954058..0000000000 --- a/docs/src/main/asciidoc/migrations.adoc +++ /dev/null @@ -1,180 +0,0 @@ -:core_path: ../../../.. -:doc_samples: {core_path}/samples/wiremock-jetty -:wiremock_tests: {core_path}/spring-cloud-contract-wiremock - -== Migrations - -TIP: For up to date migration guides please visit -the project's https://github.com/spring-cloud/spring-cloud-contract/wiki/[wiki page]. - -This section covers migrating from one version of Spring Cloud Contract Verifier to the -next version. It covers the following versions upgrade paths: - -[[cloud-verifier-1.0-1.1]] -=== 1.0.x -> 1.1.x - -This section covers upgrading from version 1.0 to version 1.1. - -==== New structure of generated stubs - -In `1.1.x` we have introduced a change to the structure of generated stubs. If you have -been using the `@AutoConfigureWireMock` notation to use the stubs from the classpath, -it no longer works. The following example shows how the `@AutoConfigureWireMock` notation -used to work: - -[source,java] ----- -@AutoConfigureWireMock(stubs = "classpath:/customer-stubs/mappings", port = 8084) ----- - -You must either change the location of the stubs to: -`classpath:.../META-INF/groupId/artifactId/version/mappings` or use the new -classpath-based `@AutoConfigureStubRunner`, as shown in the following example: - -[source,java] ----- -@AutoConfigureWireMock(stubs = "classpath:customer-stubs/META-INF/travel.components/customer-contract/1.0.2-SNAPSHOT/mappings/", port = 8084) ----- - -If you do not want to use `@AutoConfigureStubRunner` and you want to remain with the old -structure, set your plugin tasks accordingly. The following example would work for the -structure presented in the previous snippet. - -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - - - - true - - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - stub - prepare-package - - single - - false - - true - ${basedir}/src/assembly/stub.xml - - - - - - - - - - - - stubs - - jar - - false - - - ${project.build.directory}/snippets/stubs - customer-stubs/mappings - - **/* - - - - ${basedir}/src/test/resources/contracts - customer-stubs/contracts - - **/*.groovy - - - - - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -task copyStubs(type: Copy, dependsOn: 'generateWireMockClientStubs') { -// Preserve directory structure from 1.0.X of spring-cloud-contract - from "${project.buildDir}/resources/main/customer-stubs/META-INF/${project.group}/${project.name}/${project.version}" - into "${project.buildDir}/resources/main/customer-stubs" -} ----- - -[[cloud-verifier-1.1-1.2]] -=== 1.1.x -> 1.2.x - -This section covers upgrading from version 1.1 to version 1.2. - -==== Custom `HttpServerStub` - -`HttpServerStub` includes a method that was not in version 1.1. The method is -`String registeredMappings()` If you have classes that implement `HttpServerStub`, you -now have to implement the `registeredMappings()` method. It should return a `String` -representing all mappings available in a single `HttpServerStub`. - -See https://github.com/spring-cloud/spring-cloud-contract/issues/355[issue 355] for more -detail. - -==== New packages for generated tests - -The flow for setting the generated tests package name will look like this: - -* Set `basePackageForTests` -* If `basePackageForTests` was not set, pick the package from `baseClassForTests` -* If `baseClassForTests` was not set, pick `packageWithBaseClasses` -* If nothing got set, pick the default value: -`org.springframework.cloud.contract.verifier.tests` - -See https://github.com/spring-cloud/spring-cloud-contract/issues/260[issue 260] for more -detail. - -==== New Methods in TemplateProcessor - -In order to add support for `fromRequest.path`, the following methods had to be added to the -`TemplateProcessor` interface: - -* `path()` -* `path(int index)` - -See https://github.com/spring-cloud/spring-cloud-contract/issues/388[issue 388] for more -detail. - -==== RestAssured 3.0 - -Rest Assured, used in the generated test classes, got bumped to `3.0`. If -you manually set versions of Spring Cloud Contract and the release train -you might see the following exception: - -[source,bash] ----- -Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile (default-testCompile) on project some-project: Compilation failure: Compilation failure: -[ERROR] /some/path/SomeClass.java:[4,39] package com.jayway.restassured.response does not exist ----- - -This exception will occur due to the fact that the tests got generated with -an old version of plugin and at test execution time you have an incompatible -version of the release train (and vice versa). - -Done via https://github.com/spring-cloud/spring-cloud-contract/issues/267[issue 267] - -[[cloud-verifier-1.2-2.0]] -=== 1.2.x -> 2.0.x \ No newline at end of file diff --git a/docs/src/main/asciidoc/spring-cloud-contract.adoc b/docs/src/main/asciidoc/spring-cloud-contract.adoc index a0b79b8813..5b78422ed6 100644 --- a/docs/src/main/asciidoc/spring-cloud-contract.adoc +++ b/docs/src/main/asciidoc/spring-cloud-contract.adoc @@ -17,15 +17,12 @@ Olga Maciaszek-Sharma, Mariusz Smykuła, Dave Syer, Jay Bryant_ == Spring Cloud Contract You need confidence when pushing new features to a new application or service in a -distributed system. This project provides support for Consumer Driven Contracts and -service schemas in Spring applications (for both HTTP and message-based interactions), +distributed system. This project provides contract tests support for both HTTP and message-based interactions, covering a range of options for writing tests, publishing them as assets, and asserting that a contract is kept by producers and consumers. -include::spring-cloud-contract-verifier.adoc[] +include::_spring-cloud-contract-verifier.adoc[] -include::spring-cloud-wiremock.adoc[] +include::_spring-cloud-wiremock.adoc[] -include::migrations.adoc[] - -include::links.adoc[] +include::_links.adoc[]