Split files
This commit is contained in:
40
docs/modules/ROOT/pages/howto/contract-dsl-rest-docs.adoc
Normal file
40
docs/modules/ROOT/pages/howto/contract-dsl-rest-docs.adoc
Normal file
@@ -0,0 +1,40 @@
|
||||
[[contract-dsl-rest-docs]]
|
||||
= How Can I Generate Spring REST Docs Snippets from the Contracts?
|
||||
|
||||
When you want to include the requests and responses of your API by using Spring REST Docs,
|
||||
you only need to make some minor changes to your setup if you are using MockMvc and RestAssuredMockMvc.
|
||||
To do so, include the following dependencies (if you have not already done so):
|
||||
|
||||
====
|
||||
[source,xml,indent=0,subs="verbatim,attributes",role="primary"]
|
||||
.maven
|
||||
----
|
||||
include:../:{standalone_restdocs_path}/http-server/pom.xml[tags=dependencies,indent=0]
|
||||
----
|
||||
|
||||
[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"]
|
||||
.gradle
|
||||
----
|
||||
include:../:{standalone_restdocs_path}/http-server/build.gradle[tags=dependencies,indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
Next, you need to make some changes to your base class. The following examples use
|
||||
`WebAppContext` and the standalone option with RestAssured:
|
||||
|
||||
====
|
||||
[source,java,indent=0,subs="verbatim,attributes",role="primary"]
|
||||
.WebAppContext
|
||||
----
|
||||
include:../:{standalone_restdocs_path}/http-server/src/test/java/com/example/fraud/FraudBaseWithWebAppSetup.java[tags=base_class,indent=0]
|
||||
----
|
||||
|
||||
[source,java,indent=0,subs="verbatim,attributes",role="secondary"]
|
||||
.Standalone
|
||||
----
|
||||
include:../:{standalone_restdocs_path}/http-server/src/test/java/com/example/fraud/FraudBaseWithStandaloneSetup.java[tags=base_class,indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
TIP: You need not specify the output directory for the generated snippets (since version 1.2.0.RELEASE of Spring REST Docs).
|
||||
|
||||
@@ -0,0 +1,310 @@
|
||||
[[how-to-common-repo-with-contracts]]
|
||||
= How Can I use a Common Repository with Contracts Instead of Storing Them with the Producer?
|
||||
|
||||
Another way of storing contracts, rather than having them with the producer, is to keep
|
||||
them in a common place. This situation can be related to security issues (where the
|
||||
consumers cannot clone the producer's code). Also, if you keep contracts in a single place,
|
||||
then you, as a producer, know how many consumers you have and which consumer you may break
|
||||
with your local changes.
|
||||
|
||||
[[how-to-repo-structure]]
|
||||
== Repo Structure
|
||||
|
||||
Assume that we have a producer with coordinates of `com.example:server` and three
|
||||
consumers: `client1`, `client2`, and `client3`. Then, in the repository with common
|
||||
contracts, you could have the following setup (which you can check out
|
||||
https://github.com/spring-cloud/spring-cloud-contract/tree/{github-tag}/samples/standalone/contracts[here]).
|
||||
The following listing shows such a structure:
|
||||
|
||||
====
|
||||
[source,bash,indent=0]
|
||||
----
|
||||
├── com
|
||||
│ └── example
|
||||
│ └── server
|
||||
│ ├── client1
|
||||
│ │ └── expectation.groovy
|
||||
│ ├── client2
|
||||
│ │ └── expectation.groovy
|
||||
│ ├── client3
|
||||
│ │ └── expectation.groovy
|
||||
│ └── pom.xml
|
||||
├── mvnw
|
||||
├── mvnw.cmd
|
||||
├── pom.xml
|
||||
└── src
|
||||
└── assembly
|
||||
└── contracts.xml
|
||||
----
|
||||
====
|
||||
|
||||
Under the slash-delimited `groupid/artifact id` folder (`com/example/server`), you have
|
||||
expectations of the three consumers (`client1`, `client2`, and `client3`). Expectations are the standard Groovy DSL
|
||||
contract files, as described throughout this documentation. This repository has to produce a JAR file that maps
|
||||
one-to-one to the contents of the repository.
|
||||
|
||||
The following example shows a `pom.xml` file inside the `server` folder:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
include:../:{introduction_url}/samples/standalone/contracts/com/example/server/pom.xml[indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
There are no dependencies other than the Spring Cloud Contract Maven Plugin.
|
||||
Those `pom.xml` files are necessary for the consumer side to run `mvn clean install -DskipTests` to locally install
|
||||
the stubs of the producer project.
|
||||
|
||||
The `pom.xml` file in the root folder can look like the following:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
include:../:{introduction_url}/samples/standalone/contracts/pom.xml[indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
It uses the assembly plugin to build the JAR with all the contracts. The following example
|
||||
shows such a setup:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
include:../:{introduction_url}/samples/standalone/contracts/src/assembly/contracts.xml[indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
[[how-to-workflow]]
|
||||
== Workflow
|
||||
|
||||
The workflow assumes that Spring Cloud Contract is set up both on the consumer and on the
|
||||
producer side. There is also the proper plugin setup in the common repository with
|
||||
contracts. The CI jobs are set for a common repository to build an artifact of all
|
||||
contracts and upload it to Nexus or Artifactory. The following image shows the UML for this
|
||||
workflow:
|
||||
|
||||
[plantuml, how-to-common-repo, png]
|
||||
----
|
||||
"API Consumer"->"Common repo": create a folder \nfor producer [API Producer]
|
||||
"API Consumer"->"Common repo": under [API Producer] create a folder \nfor consumer \n[API Consumer]
|
||||
"API Consumer"->"Common repo": define contracts under \n[API Consumer] folder
|
||||
"API Consumer"->"Common repo": install stubs of [API Producer]\nin local storage
|
||||
"Common repo"->"Common Repo\nSCC Plugin": install stubs \nin local storage. \nDon't generate tests.
|
||||
"Common Repo\nSCC Plugin"->"Local storage": install stubs
|
||||
"Local storage"->"Common Repo\nSCC Plugin": stubs installed
|
||||
"API Consumer"->"API Consumer": write a SCC Stub Runner \nbased contract test
|
||||
"API Consumer"->"API Consumer\nSCC Stub Runner": fetch the stubs\n of [API Producer] \nfrom local storage
|
||||
"API Consumer\nSCC Stub Runner"->"Local storage": test asks for [API Producer] stubs
|
||||
"Local storage"->"API Consumer\nSCC Stub Runner": [API Producer] stubs found
|
||||
"API Consumer\nSCC Stub Runner"->"API Consumer\nSCC Stub Runner": run in memory\n HTTP server stubs
|
||||
"API Consumer\nSCC Stub Runner"->"API Consumer": HTTP server stubs running,\n ready for tests
|
||||
"API Consumer"->"API Consumer\nSCC Stub Runner": send a request \nto the HTTP server stub
|
||||
"API Consumer\nSCC Stub Runner"->"API Consumer": communication is correct. \nTests are passing
|
||||
"API Consumer"->"Common repo": file pull request \nwith contracts
|
||||
"API Producer"->"Common repo": take over \nthe pull request
|
||||
"API Producer"->"Common repo": install the JAR \nwith all contracts\n in local storage
|
||||
"Common repo"->"Local storage": install the JAR
|
||||
"Local storage"->"Common repo": contracts JAR installed
|
||||
"API Producer"->"Producer Build": run the build \nand fetch contracts from \nlocal storage
|
||||
"Producer Build"->"Producer\nSCC Plugin": generate \ntests, stubs and stubs \nartifact (e.g. stubs-jar)
|
||||
"Producer\nSCC Plugin"->"Local storage": fetch contract definitions for [API Prodcer]
|
||||
"Local storage"->"Producer\nSCC Plugin": contracts fetched
|
||||
"Producer\nSCC Plugin"->"Producer Build": tests and stubs created
|
||||
"Producer Build"->"Nexus / Artifactory": upload contracts \nand stubs and the project arifact
|
||||
"Producer Build"->"API Producer": Build successful
|
||||
"API Producer"->"Common repo": merge the pull request
|
||||
"Common repo"->"Nexus / Artifactory": upload the fresh JAR \nwith contract definitions
|
||||
"API Producer"->"API Producer": start fetching contract definitions \nfrom Nexus / Artifactory
|
||||
----
|
||||
|
||||
[[how-to-workflow-consumer]]
|
||||
== Consumer
|
||||
|
||||
When the consumer wants to work on the contracts offline, instead of cloning the producer
|
||||
code, the consumer team clones the common repository, goes to the required producer's
|
||||
folder (for example, `com/example/server`) and runs `mvn clean install -DskipTests` to
|
||||
locally install the stubs converted from the contracts.
|
||||
|
||||
TIP: You need to have https://maven.apache.org/download.cgi[Maven installed locally].
|
||||
|
||||
[[how-to-workflow-producer]]
|
||||
== Producer
|
||||
|
||||
As a producer, you can alter the Spring Cloud Contract Verifier to provide the URL and
|
||||
the dependency of the JAR that contains the contracts, as follows:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
include:../:{introduction_url}/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml[tags=remote_config,indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
With this setup, the JAR with a `groupid` of `com.example.standalone` and an `artifactid` of
|
||||
`contracts` is downloaded from `https://link/to/your/nexus/or/artifactory/or/sth`. It is
|
||||
then unpacked in a local temporary folder, and the contracts present in
|
||||
`com/example/server` are picked as the ones used to generate the tests and the stubs. Due
|
||||
to this convention, the producer team can know which consumer teams are broken when
|
||||
some incompatible changes are made.
|
||||
|
||||
The rest of the flow looks the same.
|
||||
|
||||
[[how-to-define-messaging-contracts-per-topic]]
|
||||
== How Can I Define Messaging Contracts per Topic Rather than per Producer?
|
||||
|
||||
To avoid messaging contracts duplication in the common repository, when a few producers write messages to one topic,
|
||||
we could create a structure in which the REST contracts are placed in a folder per producer and messaging
|
||||
contracts are placed in the folder per topic.
|
||||
|
||||
[[how-to-define-messaging-contracts-per-topic-maven]]
|
||||
=== For Maven Projects
|
||||
|
||||
To make it possible to work on the producer side, we should specify an inclusion pattern for
|
||||
filtering common repository jar files by messaging topics we are interested in. The
|
||||
`includedFiles` property of the Maven Spring Cloud Contract plugin
|
||||
lets us do so. Also, `contractsPath` need to be specified, since the default path would be
|
||||
the common repository `groupid/artifactid`. The following example shows a Maven
|
||||
plugin for Spring Cloud Contract:
|
||||
|
||||
====
|
||||
[source,xml,indent=0]
|
||||
----
|
||||
<plugin>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
|
||||
<version>${spring-cloud-contract.version}</version>
|
||||
<configuration>
|
||||
<contractsMode>REMOTE</contractsMode>
|
||||
<contractsRepositoryUrl>https://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl>
|
||||
<contractDependency>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>common-repo-with-contracts</artifactId>
|
||||
<version>+</version>
|
||||
</contractDependency>
|
||||
<contractsPath>/</contractsPath>
|
||||
<baseClassMappings>
|
||||
<baseClassMapping>
|
||||
<contractPackageRegex>.*messaging.*</contractPackageRegex>
|
||||
<baseClassFQN>com.example.services.MessagingBase</baseClassFQN>
|
||||
</baseClassMapping>
|
||||
<baseClassMapping>
|
||||
<contractPackageRegex>.*rest.*</contractPackageRegex>
|
||||
<baseClassFQN>com.example.services.TestBase</baseClassFQN>
|
||||
</baseClassMapping>
|
||||
</baseClassMappings>
|
||||
<includedFiles>
|
||||
<includedFile>**/${project.artifactId}/**</includedFile>
|
||||
<includedFile>**/${first-topic}/**</includedFile>
|
||||
<includedFile>**/${second-topic}/**</includedFile>
|
||||
</includedFiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
----
|
||||
====
|
||||
|
||||
NOTE: Many of the values in the preceding Maven plugin can be changed. We included it for
|
||||
illustration purposes rather than trying to provide a "`typical`" example.
|
||||
|
||||
[[how-to-define-messaging-contracts-per-topic-gradle]]
|
||||
=== For Gradle Projects
|
||||
|
||||
To work with a Gradle project:
|
||||
|
||||
. Add a custom configuration for the common repository dependency, as follows:
|
||||
+
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
ext {
|
||||
contractsGroupId = "com.example"
|
||||
contractsArtifactId = "common-repo"
|
||||
contractsVersion = "1.2.3"
|
||||
}
|
||||
|
||||
configurations {
|
||||
contracts {
|
||||
transitive = false
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
. Add the common repository dependency to your classpath, as follows:
|
||||
+
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
dependencies {
|
||||
contracts "${contractsGroupId}:${contractsArtifactId}:${contractsVersion}"
|
||||
testCompile "${contractsGroupId}:${contractsArtifactId}:${contractsVersion}"
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
. Download the dependency to an appropriate folder, as follows:
|
||||
+
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
task getContracts(type: Copy) {
|
||||
from configurations.contracts
|
||||
into new File(project.buildDir, "downloadedContracts")
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
. Unzip the JAR, as follows:
|
||||
+
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
task unzipContracts(type: Copy) {
|
||||
def zipFile = new File(project.buildDir, "downloadedContracts/${contractsArtifactId}-${contractsVersion}.jar")
|
||||
def outputDir = file("${buildDir}/unpackedContracts")
|
||||
|
||||
from zipTree(zipFile)
|
||||
into outputDir
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
. Cleanup unused contracts, as follows:
|
||||
+
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
task deleteUnwantedContracts(type: Delete) {
|
||||
delete fileTree(dir: "${buildDir}/unpackedContracts",
|
||||
include: "**/*",
|
||||
excludes: [
|
||||
"**/${project.name}/**"",
|
||||
"**/${first-topic}/**",
|
||||
"**/${second-topic}/**"])
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
. Create task dependencies, as follows:
|
||||
+
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
unzipContracts.dependsOn("getContracts")
|
||||
deleteUnwantedContracts.dependsOn("unzipContracts")
|
||||
build.dependsOn("deleteUnwantedContracts")
|
||||
----
|
||||
====
|
||||
|
||||
. Configure the plugin by specifying the directory that contains the contracts, by setting
|
||||
the `contractsDslDir` property, as follows:
|
||||
+
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
contracts {
|
||||
contractsDslDir = new File("${buildDir}/unpackedContracts")
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
17
docs/modules/ROOT/pages/howto/how-to-debug-wiremock.adoc
Normal file
17
docs/modules/ROOT/pages/howto/how-to-debug-wiremock.adoc
Normal file
@@ -0,0 +1,17 @@
|
||||
[[how-to-debug-wiremock]]
|
||||
= How Can I Debug the Mapping, Request, or Response Being Sent by WireMock?
|
||||
|
||||
Starting from version `1.2.0`, we set WireMock logging to
|
||||
`info` and set the WireMock notifier to being verbose. Now you can
|
||||
exactly know what request was received by the WireMock server and which
|
||||
matching response definition was picked.
|
||||
|
||||
To turn off this feature, set WireMock logging to `ERROR`, as follows:
|
||||
|
||||
====
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
logging.level.com.github.tomakehurst.wiremock=ERROR
|
||||
----
|
||||
====
|
||||
|
||||
18
docs/modules/ROOT/pages/howto/how-to-debug.adoc
Normal file
18
docs/modules/ROOT/pages/howto/how-to-debug.adoc
Normal file
@@ -0,0 +1,18 @@
|
||||
[[how-to-debug]]
|
||||
= How Can I Debug the Request/Response Being Sent by the Generated Tests Client?
|
||||
|
||||
The generated tests all boil down to RestAssured in some form or fashion. RestAssured
|
||||
relies on the https://hc.apache.org/httpcomponents-client-ga/[Apache HttpClient].
|
||||
HttpClient has a facility called
|
||||
https://hc.apache.org/httpcomponents-client-ga/logging.html#Wire_Logging[wire logging],
|
||||
which logs the entire request and response to HttpClient. Spring Boot has a logging
|
||||
https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html[common application property]
|
||||
for doing this sort of thing. To use it, add it to your application properties, as follows:
|
||||
|
||||
====
|
||||
[source,properties,indent=0]
|
||||
----
|
||||
logging.level.org.apache.http.wire=DEBUG
|
||||
----
|
||||
====
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
[[how-to-do-stubs-versioning]]
|
||||
= How to Do Stubs versioning?
|
||||
|
||||
This section covers versioning of the stubs, which you can handle in a number of different ways:
|
||||
|
||||
* <<how-to-api-versioning>>
|
||||
* <<how-to-jar-versioning>>
|
||||
* <<how-to-dev-or-prod-stubs>>
|
||||
|
||||
[[how-to-api-versioning]]
|
||||
== API Versioning
|
||||
|
||||
What does versioning really mean? If you refer to the API version, there are
|
||||
different approaches:
|
||||
|
||||
- Use hypermedia links and do not version your API by any means
|
||||
- Pass the version through headers and URLs
|
||||
|
||||
We do not try to answer the question of which approach is better. You should pick whatever
|
||||
suits your needs and lets you generate business value.
|
||||
|
||||
Assume that you do version your API. In that case, you should provide as many contracts with as many versions as you support.
|
||||
You can create a subfolder for every version or append it to the contract name -- whatever suits you best.
|
||||
|
||||
[[how-to-jar-versioning]]
|
||||
== JAR versioning
|
||||
|
||||
If, by versioning, you mean the version of the JAR that contains the stubs, then there are essentially two main approaches.
|
||||
|
||||
Assume that you do continuous delivery and deployment, which means that you generate a new version of
|
||||
the jar each time you go through the pipeline and that the jar can go to production at any time. For example, your jar version
|
||||
looks like the following (because it got built on the 20.10.2016 at 20:15:21) :
|
||||
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
1.0.0.20161020-201521-RELEASE
|
||||
----
|
||||
====
|
||||
|
||||
In that case, your generated stub jar should look like the following:
|
||||
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
1.0.0.20161020-201521-RELEASE-stubs.jar
|
||||
----
|
||||
====
|
||||
|
||||
In this case, you should, inside your `application.yml` or `@AutoConfigureStubRunner` when
|
||||
referencing stubs, provide the latest version of the stubs. You can do that by passing the
|
||||
`+` sign. the following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})
|
||||
----
|
||||
====
|
||||
|
||||
If the versioning, however, is fixed (for example, `1.0.4.RELEASE` or `2.1.1`), you have to set the concrete value of the jar
|
||||
version. The following example shows how to do so for version 2.1.1:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:2.1.1:stubs:8080"})
|
||||
----
|
||||
====
|
||||
|
||||
[[how-to-dev-or-prod-stubs]]
|
||||
== Development or Production Stubs
|
||||
|
||||
You can manipulate the classifier to run the tests against the current development version
|
||||
of the stubs of other services or the ones that were deployed to production. If you alter
|
||||
your build to deploy the stubs with the `prod-stubs` classifier once you reach production
|
||||
deployment, you can run tests in one case with development stubs and in another case with production stubs.
|
||||
|
||||
The following example works for tests that use the development version of the stubs:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:8080"})
|
||||
----
|
||||
====
|
||||
|
||||
The following example works for tests that use the production version of stubs:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:prod-stubs:8080"})
|
||||
----
|
||||
====
|
||||
|
||||
You can also pass those values also in properties from your deployment pipeline.
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
[[how-to-generate-pact-from-scc]]
|
||||
= How Can I Generate Pact, YAML, or X files from Spring Cloud Contract Contracts?
|
||||
|
||||
Spring Cloud Contract comes with a `ToFileContractsTransformer` class that lets you dump
|
||||
contracts as files for the given `ContractConverter`. It contains a `static void main`
|
||||
method that lets you run the transformer as an executable. It takes the following
|
||||
arguments:
|
||||
|
||||
- argument 1 : `FQN`: Fully qualified name of the `ContractConverter` (for example, `PactContractConverter`). *REQUIRED*.
|
||||
- argument 2 : `path`: Path where the dumped files should be stored. *OPTIONAL* -- defaults to `target/converted-contracts`.
|
||||
- argument 3 : `path`: Path were the contracts should be searched for. *OPTIONAL* -- defaults to `src/test/resources/contracts`.
|
||||
|
||||
After calling the transformer, the Spring Cloud Contract files are processed and,
|
||||
depending on the provided FQN of the `ContractTransformer`, the contracts are transformed
|
||||
to the required format and dumped to the provided folder.
|
||||
|
||||
The following example shows how to configure Pact integration for both Maven and Gradle:
|
||||
|
||||
====
|
||||
[source,xml,indent=0,role="primary"]
|
||||
.Maven
|
||||
----
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>convert-dsl-to-pact</id>
|
||||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<classpathScope>test</classpathScope>
|
||||
<mainClass>
|
||||
org.springframework.cloud.contract.verifier.util.ToFileContractsTransformer
|
||||
</mainClass>
|
||||
<arguments>
|
||||
<argument>
|
||||
org.springframework.cloud.contract.verifier.spec.pact.PactContractConverter
|
||||
</argument>
|
||||
<argument>${project.basedir}/target/pacts</argument>
|
||||
<argument>
|
||||
${project.basedir}/src/test/resources/contracts
|
||||
</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
----
|
||||
|
||||
[source,groovy,indent=0,role="secondary"]
|
||||
.Gradle
|
||||
----
|
||||
task convertContracts(type: JavaExec) {
|
||||
main = "org.springframework.cloud.contract.verifier.util.ToFileContractsTransformer"
|
||||
classpath = sourceSets.test.compileClasspath
|
||||
args("org.springframework.cloud.contract.verifier.spec.pact.PactContractConverter",
|
||||
"${project.rootDir}/build/pacts", "${project.rootDir}/src/test/resources/contracts")
|
||||
}
|
||||
|
||||
test.dependsOn("convertContracts")
|
||||
----
|
||||
====
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[[how-to-generate-stubs-at-runtime]]
|
||||
= How Can I Generate Stubs at Runtime
|
||||
|
||||
If you want to generate stubs at runtime for contracts, switch the `generateStubs` property in the `@AutoConfigureStubRunner` annotation, or call the `withGenerateStubs(true)` method on the JUnit Rule or Extension. You can read more about this in <<project-features.adoc#features-stub-runner-generate-stubs-at-runtime, this section>> of the documentation.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[[how-to-mark-contract-in-progress]]
|
||||
= How Can I Mark that a Contract Is in Progress
|
||||
|
||||
If a contract is in progress, it means that the, on the producer side, tests are not generated, but the stub is generated. You can read more about this in <<project-features.adoc#contract-dsl-in-progress, this section>> of the documentation.
|
||||
|
||||
In a CI build, before going to production, you would like to ensure that no in-progress contracts are on the classpath, because they may lead to false positives. For this reason, by default, in the Spring Cloud Contract plugin, we set the value of `failOnInProgress` to `true`. If you want to allow such contracts when tests are to be generated, set the flag to `false`.
|
||||
@@ -0,0 +1,7 @@
|
||||
[[how-to-not-write-contracts-in-groovy]]
|
||||
= How Can I Write Contracts in a Language Other than Groovy?
|
||||
|
||||
You can write a contract in YAML. See <<project-features.adoc#contract-dsl, this section>> for more information.
|
||||
|
||||
We are working on allowing more ways of describing the contracts. You can check the {github-issues}[github-issues] for more information.
|
||||
|
||||
106
docs/modules/ROOT/pages/howto/how-to-provide-dynamic-values.adoc
Normal file
106
docs/modules/ROOT/pages/howto/how-to-provide-dynamic-values.adoc
Normal file
@@ -0,0 +1,106 @@
|
||||
[[how-to-provide-dynamic-values]]
|
||||
= How Can I Provide Dynamic Values to a Contract?
|
||||
|
||||
One of the biggest challenges related to stubs is their reusability. Only if they can be widely used can they serve their purpose.
|
||||
The hard-coded values (such as dates and IDs) of request and response elements generally make that difficult.
|
||||
Consider the following JSON request:
|
||||
|
||||
====
|
||||
[source,json,indent=0]
|
||||
----
|
||||
{
|
||||
"time" : "2016-10-10 20:10:15",
|
||||
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
|
||||
"body" : "foo"
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Now consider the following JSON response:
|
||||
|
||||
====
|
||||
[source,json,indent=0]
|
||||
----
|
||||
{
|
||||
"time" : "2016-10-10 21:10:15",
|
||||
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
|
||||
"body" : "bar"
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Imagine the pain required to set the proper value of the `time` field (assume that this content is generated by the
|
||||
database) by changing the clock in the system or by providing stub implementations of data providers. The same is related
|
||||
to the `id` field. You could create a stubbed implementation of UUID generator, but doing so makes little sense.
|
||||
|
||||
So, as a consumer, you want to send a request that matches any form of a time or any UUID. That way, your system
|
||||
works as usual, generating data without you having to stub out anything. Assume that, in case of the aforementioned
|
||||
JSON, the most important part is the `body` field. You can focus on that and provide matching for other fields. In other words,
|
||||
you would like the stub to work as follows:
|
||||
|
||||
====
|
||||
[source,json,indent=0]
|
||||
----
|
||||
{
|
||||
"time" : "SOMETHING THAT MATCHES TIME",
|
||||
"id" : "SOMETHING THAT MATCHES UUID",
|
||||
"body" : "foo"
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
As far as the response goes, as a consumer, you need a concrete value on which you can operate.
|
||||
Consequently, the following JSON is valid:
|
||||
|
||||
====
|
||||
[source,json,indent=0]
|
||||
----
|
||||
{
|
||||
"time" : "2016-10-10 21:10:15",
|
||||
"id" : "c4231e1f-3ca9-48d3-b7e7-567d55f0d051",
|
||||
"body" : "bar"
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
In the previous sections, we generated tests from contracts. So, from the producer's side, the situation looks
|
||||
much different. We parse the provided contract, and, in the test, we want to send a real request to your endpoints.
|
||||
So, for the case of a producer for the request, we cannot have any sort of matching. We need concrete values on which the
|
||||
producer's backend can work. Consequently, the following JSON would be valid:
|
||||
|
||||
====
|
||||
[source,json,indent=0]
|
||||
----
|
||||
{
|
||||
"time" : "2016-10-10 20:10:15",
|
||||
"id" : "9febab1c-6f36-4a0b-88d6-3b6a6d81cd4a",
|
||||
"body" : "foo"
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
On the other hand, from the point of view of the validity of the contract, the response does not necessarily have to
|
||||
contain concrete values for `time` or `id`. Suppose you generate those on the producer side. Again, you
|
||||
have to do a lot of stubbing to ensure that you always return the same values. That is why, from the producer's side,
|
||||
you might want the following response:
|
||||
|
||||
====
|
||||
[source,json,indent=0]
|
||||
----
|
||||
{
|
||||
"time" : "SOMETHING THAT MATCHES TIME",
|
||||
"id" : "SOMETHING THAT MATCHES UUID",
|
||||
"body" : "bar"
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
How can you then provide a matcher for the consumer and a concrete value for the producer (and the opposite at some other time)?
|
||||
Spring Cloud Contract lets you provide a dynamic value. That means that it can differ for both
|
||||
sides of the communication.
|
||||
|
||||
You can read more about this in the <<project-features.adoc#contract-dsl, Contract DSL>> section.
|
||||
|
||||
IMPORTANT: Read the https://groovy-lang.org/json.html[Groovy docs related to JSON] to understand how to
|
||||
properly structure the request and response bodies.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[[how-to-reference-text-from-file]]
|
||||
= How Can I Reference Text from File?
|
||||
|
||||
In version 1.2.0, we added this ability. You can call a `file(...)` method in the
|
||||
DSL and provide a path relative to where the contract lies.
|
||||
If you use YAML, you can use the `bodyFromFile` property.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[[how-to-see-registered-stubs]]
|
||||
= How Can I See What Got Registered in the HTTP Server Stub?
|
||||
|
||||
You can use the `mappingsOutputFolder` property on `@AutoConfigureStubRunner`, `StubRunnerRule`, or
|
||||
`StubRunnerExtension` to dump all mappings for each artifact ID. Also, the port at which the given stub server
|
||||
was started is attached.
|
||||
|
||||
279
docs/modules/ROOT/pages/howto/how-to-use-git-as-storage.adoc
Normal file
279
docs/modules/ROOT/pages/howto/how-to-use-git-as-storage.adoc
Normal file
@@ -0,0 +1,279 @@
|
||||
[[how-to-use-git-as-storage]]
|
||||
= How Can I Use Git as the Storage for Contracts and Stubs?
|
||||
|
||||
In the polyglot world, there are languages that do not use binary storage, as
|
||||
Artifactory and Nexus do. Starting from Spring Cloud Contract version 2.0.0, we provide
|
||||
mechanisms to store contracts and stubs in a SCM (Source Control Management) repository. Currently, the
|
||||
only supported SCM is Git.
|
||||
|
||||
The repository would have to have the following setup
|
||||
(which you can checkout from https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/{samples_branch}/contracts_git/[here]):
|
||||
|
||||
====
|
||||
[source,indent=0]
|
||||
----
|
||||
.
|
||||
└── META-INF
|
||||
└── com.example
|
||||
└── beer-api-producer-git
|
||||
└── 0.0.1-SNAPSHOT
|
||||
├── contracts
|
||||
│ └── beer-api-consumer
|
||||
│ ├── messaging
|
||||
│ │ ├── shouldSendAcceptedVerification.groovy
|
||||
│ │ └── shouldSendRejectedVerification.groovy
|
||||
│ └── rest
|
||||
│ ├── shouldGrantABeerIfOldEnough.groovy
|
||||
│ └── shouldRejectABeerIfTooYoung.groovy
|
||||
└── mappings
|
||||
└── beer-api-consumer
|
||||
└── rest
|
||||
├── shouldGrantABeerIfOldEnough.json
|
||||
└── shouldRejectABeerIfTooYoung.json
|
||||
----
|
||||
====
|
||||
|
||||
Under the `META-INF` folder:
|
||||
|
||||
* We group applications by `groupId` (such as `com.example`).
|
||||
* Each application is represented by its `artifactId` (for example, `beer-api-producer-git`).
|
||||
* Next, each application is organized by its version (such as `0.0.1-SNAPSHOT`). Starting
|
||||
from Spring Cloud Contract version `2.1.0`, you can specify the versions as follows
|
||||
(assuming that your versions follow semantic versioning):
|
||||
** `+` or `latest`: To find the latest version of your stubs (assuming that the snapshots
|
||||
are always the latest artifact for a given revision number). That means:
|
||||
*** If you have `1.0.0.RELEASE`, `2.0.0.BUILD-SNAPSHOT`, and `2.0.0.RELEASE`, we assume
|
||||
that the latest is `2.0.0.BUILD-SNAPSHOT`.
|
||||
*** If you have `1.0.0.RELEASE` and `2.0.0.RELEASE`, we assume that the latest is `2.0.0.RELEASE`.
|
||||
*** If you have a version called `latest` or `+`, we will pick that folder.
|
||||
** `release`: To find the latest release version of your stubs. That means:
|
||||
*** If you have `1.0.0.RELEASE`, `2.0.0.BUILD-SNAPSHOT`, and `2.0.0.RELEASE` we assume
|
||||
that the latest is `2.0.0.RELEASE`.
|
||||
*** If you have a version called `release`, we pick that folder.
|
||||
|
||||
Finally, there are two folders:
|
||||
|
||||
* `contracts`: The good practice is to store the contracts required by each
|
||||
consumer in the folder with the consumer name (such as `beer-api-consumer`). That way, you
|
||||
can use the `stubs-per-consumer` feature. Further directory structure is arbitrary.
|
||||
* `mappings`: The Maven or Gradle Spring Cloud Contract plugins push
|
||||
the stub server mappings in this folder. On the consumer side, Stub Runner scans this folder
|
||||
to start stub servers with stub definitions. The folder structure is a copy
|
||||
of the one created in the `contracts` subfolder.
|
||||
|
||||
[[how-to-protocol-convention]]
|
||||
== Protocol Convention
|
||||
|
||||
To control the type and location of the source of contracts (whether
|
||||
binary storage or an SCM repository), you can use the protocol in the URL of
|
||||
the repository. Spring Cloud Contract iterates over registered protocol resolvers
|
||||
and tries to fetch the contracts (by using a plugin) or stubs (from Stub Runner).
|
||||
|
||||
For the SCM functionality, currently, we support the Git repository. To use it,
|
||||
in the property where the repository URL needs to be placed, you have to prefix
|
||||
the connection URL with `git://`. The following listing shows some examples:
|
||||
|
||||
====
|
||||
[source,indent=0]
|
||||
----
|
||||
git://file:///foo/bar
|
||||
git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git
|
||||
git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git
|
||||
----
|
||||
====
|
||||
|
||||
[[how-to-protocol-convention-producer]]
|
||||
== Producer
|
||||
|
||||
For the producer, to use the SCM (Source Control Management) approach, we can reuse the
|
||||
same mechanism we use for external contracts. We route Spring Cloud Contract
|
||||
to use the SCM implementation from the URL that starts with
|
||||
the `git://` protocol.
|
||||
|
||||
IMPORTANT: You have to manually add the `pushStubsToScm`
|
||||
goal in Maven or use (bind) the `pushStubsToScm` task in
|
||||
Gradle. We do not push stubs to the `origin` of your git
|
||||
repository.
|
||||
|
||||
The following listing includes the relevant parts both Maven and Gradle build files:
|
||||
|
||||
====
|
||||
[source,xml,indent=0,role="primary"]
|
||||
.Maven
|
||||
----
|
||||
<plugin>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
|
||||
<version>${spring-cloud-contract.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<!-- Base class mappings etc. -->
|
||||
|
||||
<!-- We want to pick contracts from a Git repository -->
|
||||
<contractsRepositoryUrl>git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</contractsRepositoryUrl>
|
||||
|
||||
<!-- We reuse the contract dependency section to set up the path
|
||||
to the folder that contains the contract definitions. In our case the
|
||||
path will be /groupId/artifactId/version/contracts -->
|
||||
<contractDependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</contractDependency>
|
||||
|
||||
<!-- The contracts mode can't be classpath -->
|
||||
<contractsMode>REMOTE</contractsMode>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<!-- By default we will not push the stubs back to SCM,
|
||||
you have to explicitly add it as a goal -->
|
||||
<goal>pushStubsToScm</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
----
|
||||
|
||||
[source,groovy,indent=0,role="secondary"]
|
||||
.Gradle
|
||||
----
|
||||
contracts {
|
||||
// We want to pick contracts from a Git repository
|
||||
contractDependency {
|
||||
stringNotation = "${project.group}:${project.name}:${project.version}"
|
||||
}
|
||||
/*
|
||||
We reuse the contract dependency section to set up the path
|
||||
to the folder that contains the contract definitions. In our case the
|
||||
path will be /groupId/artifactId/version/contracts
|
||||
*/
|
||||
contractRepository {
|
||||
repositoryUrl = "git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git"
|
||||
}
|
||||
// The mode can't be classpath
|
||||
contractsMode = "REMOTE"
|
||||
// Base class mappings etc.
|
||||
}
|
||||
|
||||
/*
|
||||
In this scenario we want to publish stubs to SCM whenever
|
||||
the `publish` task is invoked
|
||||
*/
|
||||
publish.dependsOn("publishStubsToScm")
|
||||
----
|
||||
====
|
||||
|
||||
You can also further customize the `publishStubsToScm` gradle task. In the following example,
|
||||
the task is customized to pick contracts from a local git repository:
|
||||
|
||||
====
|
||||
[source,groovy,indent=0]
|
||||
.gradle
|
||||
----
|
||||
publishStubsToScm {
|
||||
// We want to modify the default set up of the plugin when publish stubs to scm is called
|
||||
// We want to pick contracts from a Git repository
|
||||
contractDependency {
|
||||
stringNotation = "${project.group}:${project.name}:${project.version}"
|
||||
}
|
||||
/*
|
||||
We reuse the contract dependency section to set up the path
|
||||
to the folder that contains the contract definitions. In our case the
|
||||
path will be /groupId/artifactId/version/contracts
|
||||
*/
|
||||
contractRepository {
|
||||
repositoryUrl = "git://file://${new File(project.rootDir, "../target")}/contract_empty_git/"
|
||||
}
|
||||
// We set the contracts mode to `LOCAL`
|
||||
contractsMode = "LOCAL"
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
IMPORTANT:: Starting with the `2.3.0.RELEASE`, the `customize{}` closure previously used for the
|
||||
`publishStubsToScm` customization is no longer available. The settings should be applied directly
|
||||
within the `publishStubsToScm` closure, as in the preceding example.
|
||||
|
||||
With such a setup:
|
||||
|
||||
* A git project is cloned to a temporary directory
|
||||
* The SCM stub downloader goes to the `META-INF/groupId/artifactId/version/contracts` folder
|
||||
to find contracts. For example, for `com.example:foo:1.0.0`, the path would be
|
||||
`META-INF/com.example/foo/1.0.0/contracts`.
|
||||
* Tests are generated from the contracts.
|
||||
* Stubs are created from the contracts.
|
||||
* Once the tests pass, the stubs are committed in the cloned repository.
|
||||
* Finally, a push is sent to that repo's `origin`.
|
||||
|
||||
[[how-to-protocol-convention-producer-with-contracts-stored-locally]]
|
||||
== Producer with Contracts Stored Locally
|
||||
|
||||
Another option to use the SCM as the destination for stubs and contracts is to store the
|
||||
contracts locally, with the producer, and only push the contracts and the stubs to SCM.
|
||||
The following listing shows the setup required to achieve this with Maven and Gradle:
|
||||
|
||||
====
|
||||
[source,xml,indent=0,role="primary"]
|
||||
.Maven
|
||||
----
|
||||
include:../:{samples_url}/producer_with_empty_git/pom.xml[tags=plugin,indent=0]
|
||||
----
|
||||
|
||||
[source,groovy,indent=0,role="secondary"]
|
||||
.Gradle
|
||||
----
|
||||
include:../:{samples_url}/producer_with_empty_git/build.gradle[tags=plugin,indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
With such a setup:
|
||||
|
||||
* Contracts from the default `src/test/resources/contracts` directory are picked.
|
||||
* Tests are generated from the contracts.
|
||||
* Stubs are created from the contracts.
|
||||
* Once the tests pass:
|
||||
** The git project is cloned to a temporary directory.
|
||||
** The stubs and contracts are committed in the cloned repository.
|
||||
* Finally, a push is done to that repository's `origin`.
|
||||
|
||||
[[how-to-protocol-convention-contracts-producer-stubs-external]]
|
||||
== Keeping Contracts with the Producer and Stubs in an External Repository
|
||||
|
||||
You can also keep the contracts in the producer repository but keep the stubs in an external git repository.
|
||||
This is most useful when you want to use the base consumer-producer collaboration flow but cannot
|
||||
use an artifact repository to store the stubs.
|
||||
|
||||
To do so, use the usual producer setup and then add the `pushStubsToScm` goal and set
|
||||
`contractsRepositoryUrl` to the repository where you want to keep the stubs.
|
||||
|
||||
[[how-to-protocol-convention-contracts-producer-stubs-external-consumer]]
|
||||
== Consumer
|
||||
|
||||
On the consumer side, when passing the `repositoryRoot` parameter,
|
||||
either from the `@AutoConfigureStubRunner` annotation, the
|
||||
JUnit 4 rule, JUnit 5 extension, or properties, you can pass the URL of the
|
||||
SCM repository, prefixed with the `git://` protocol. The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@AutoConfigureStubRunner(
|
||||
stubsMode="REMOTE",
|
||||
repositoryRoot="git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git",
|
||||
ids="com.example:bookstore:0.0.1.RELEASE"
|
||||
)
|
||||
----
|
||||
====
|
||||
|
||||
With such a setup:
|
||||
|
||||
* The git project is cloned to a temporary directory.
|
||||
* The SCM stub downloader goes to the `META-INF/groupId/artifactId/version/` folder
|
||||
to find stub definitions and contracts. For example, for `com.example:foo:1.0.0`, the path would be
|
||||
`META-INF/com.example/foo/1.0.0/`.
|
||||
* Stub servers are started and fed with mappings.
|
||||
* Messaging definitions are read and used in the messaging tests.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
[[how-to-use-stubs-from-a-location]]
|
||||
= How Can I Use Stubs from a Location
|
||||
|
||||
If you want to fetch contracts or stubs from a given location without cloning a repository or fetching a JAR, use the `stubs://` protocol when providing the repository root argument for Stub Runner or the Spring Cloud Contract plugin. You can read more about this in <<project-features.adoc#features-stub-runner-stubs-protocol, this section>> of the documentation.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
[[how-to-use-the-failonnostubs-feature]]
|
||||
= How Can I Make The Build Pass if There Are No Contracts or Stubs
|
||||
|
||||
If you want Stub Runner not to fail if no stubs were found, switch the `generateStubs` property in the `@AutoConfigureStubRunner` annotation or call the `withFailOnNoStubs(false)` method on the JUnit Rule or Extension. You can read more about this in <<project-features.adoc#features-stub-runner-fail-on-no-stubs, this section>> of the documentation.
|
||||
|
||||
If you want the plugins not to fail the build when no contracts were found, you can set the `failOnNoStubs` flag in Maven or call the `contractRepository { failOnNoStubs(false) }` closure in Gradle.
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
[[how-to-work-with-transitivie]]
|
||||
= How Can I Work with Transitive Dependencies?
|
||||
|
||||
The Spring Cloud Contract plugins 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
|
||||
that stub's dependencies. When building a Maven artifact, even though you have a couple
|
||||
of different jars, all of them share one `pom.xml` file, as the following listing shows:
|
||||
|
||||
====
|
||||
[source,bash,indent=0]
|
||||
----
|
||||
├── producer-0.0.1.BUILD-20160903.075506-1-stubs.jar
|
||||
├── producer-0.0.1.BUILD-20160903.075506-1-stubs.jar.sha1
|
||||
├── producer-0.0.1.BUILD-20160903.075655-2-stubs.jar
|
||||
├── producer-0.0.1.BUILD-20160903.075655-2-stubs.jar.sha1
|
||||
├── producer-0.0.1.BUILD-SNAPSHOT.jar
|
||||
├── producer-0.0.1.BUILD-SNAPSHOT.pom
|
||||
├── producer-0.0.1.BUILD-SNAPSHOT-stubs.jar
|
||||
├── ...
|
||||
└── ...
|
||||
----
|
||||
====
|
||||
|
||||
There are three possibilities of working with those dependencies so as not to have any
|
||||
issues with transitive dependencies:
|
||||
|
||||
* Mark all application dependencies as optional
|
||||
* Create a separate `artifactid` for the stubs
|
||||
* Exclude dependencies on the consumer side
|
||||
|
||||
[[how-to-work-with-transitivie-optional]]
|
||||
== How Can I Mark All Application Dependencies as Optional?
|
||||
|
||||
If, in the `producer` application, you mark all of your dependencies as optional,
|
||||
when you include the `producer` stubs in another application (or when that
|
||||
dependency gets downloaded by Stub Runner), then, since all of the dependencies are
|
||||
optional, they do not get downloaded.
|
||||
|
||||
[[how-to-work-with-transitivie-separate]]
|
||||
== How can I Create a Separate `artifactid` for the Stubs?
|
||||
|
||||
If you create a separate `artifactid`, you can set it up in whatever way you wish.
|
||||
For example, you might decide to have no dependencies at all.
|
||||
|
||||
[[how-to-work-with-transitivie-exclude]]
|
||||
== How can I Exclude Dependencies on the Consumer Side?
|
||||
|
||||
As a consumer, if you add the stub dependency to your classpath, you can explicitly exclude the unwanted dependencies.
|
||||
|
||||
16
docs/modules/ROOT/pages/howto/why-spring-cloud-contract.adoc
Normal file
16
docs/modules/ROOT/pages/howto/why-spring-cloud-contract.adoc
Normal file
@@ -0,0 +1,16 @@
|
||||
[[why-spring-cloud-contract]]
|
||||
= Why use Spring Cloud Contract?
|
||||
|
||||
Spring Cloud Contract works great in a polyglot environment. This project has a lot of
|
||||
really interesting features. Quite a few of these features definitely make
|
||||
Spring Cloud Contract Verifier stand out on the market of Consumer Driven Contract
|
||||
(CDC) tooling. The most interesting features include the following:
|
||||
|
||||
- Ability to do CDC with messaging.
|
||||
- Clear and easy to use, statically typed DSL.
|
||||
- Ability to copy-paste your current JSON file to the contract and edit only its elements.
|
||||
- Automatic generation of tests from the defined contract.
|
||||
- Stub Runner functionality: The stubs are automatically downloaded at runtime from Nexus or Artifactory.
|
||||
- Spring Cloud integration: No discovery service is needed for integration tests.
|
||||
- Ability to add support for any language & framework through Docker.
|
||||
|
||||
Reference in New Issue
Block a user