diff --git a/docs/src/main/asciidoc/_project-features-stubrunner.adoc b/docs/src/main/asciidoc/_project-features-stubrunner.adoc index 35d9f47b55..508e1fa2e4 100644 --- a/docs/src/main/asciidoc/_project-features-stubrunner.adoc +++ b/docs/src/main/asciidoc/_project-features-stubrunner.adoc @@ -854,6 +854,124 @@ Then only the stubs registered under a path that contains the `foo-consumer` in See https://github.com/spring-cloud/spring-cloud-contract/issues/224[issue 224] for more information about the reasons behind this change. +[[features-stub-runner-stubs-protocol]] +=== Fetching Stubs or Contract Definitions From A Location + +Instead of picking the stubs or contract definitions from +Artifactory / Nexus or Git, one can just want to point to +a location on drive or classpath. This can be especially useful in a multimodule project, where one module wants +to reuse stubs or contracts from another module without +the need to actually install those in a local maven +repository ot commit those changes to Git. + +In order to achieve this it's enough to use the `stubs://` +protocol when the repository root parameter is set either +in Stub Runner or in a Spring Cloud Contract plugin. + +In this example the `producer` project has been successfully +built and stubs were generated under the `target/stubs` folder. As a consumer one can setup the Stub Runner to pick the stubs from that location using the `stubs://` protocol. + +==== +[source,java,indent=0,subs="verbatim,attributes",role="primary"] +.Annotation +---- +@AutoConfigureStubRunner( +stubsMode = StubRunnerProperties.StubsMode.REMOTE, + repositoryRoot = "stubs://file://location/to/the/producer/target/stubs/", + ids = "com.example:some-producer") +---- + +[source,java,indent=0,subs="verbatim,attributes",role="secondary"] +.JUnit 4 Rule +---- +@Rule + public StubRunnerRule rule = new StubRunnerRule() + .downloadStub("com.example:some-producer") + .repoRoot("stubs://file://location/to/the/producer/target/stubs/") + .stubsMode(StubRunnerProperties.StubsMode.REMOTE); +---- + +[source,java,indent=0,subs="verbatim,attributes",role="secondary"] +.JUnit 5 Extension +---- +@RegisterExtension + public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() + .downloadStub("com.example:some-producer") + .repoRoot("stubs://file://location/to/the/producer/target/stubs/") + .stubsMode(StubRunnerProperties.StubsMode.REMOTE); +---- +==== + +Contracts and stubs may be stored in a location, where each producer has its own, dedicated folder for contracts and stub mappings. Under that folder each consumer can have its own setup. To make Stub Runner find the dedicated folder from the provided ids one can pass a property `stubs.find-producer=true` or a system property `stubrunner.stubs.find-producer=true` . + +[source,bash,indent=0] +==== +└── com.example <1> + ├── some-artifact-id <2> + │   └── 0.0.1 + │   ├── contracts <3> + │   │   └── shouldReturnStuffForArtifactId.groovy + │   └── mappings <4> + │   └── shouldReturnStuffForArtifactId.json + └── some-other-artifact-id <5> + ├── contracts + │   └── shouldReturnStuffForOtherArtifactId.groovy + └── mappings + └── shouldReturnStuffForOtherArtifactId.json + +==== +<1> group id of the consumers +<2> consumer with artifact id [some-artifact-id] +<3> contracts for the consumer with artifact id [some-artifact-id] +<4> mappings for the consumer with artifact id [some-artifact-id] +<5> consumer with artifact id [some-other-artifact-id] + +==== +[source,java,indent=0,subs="verbatim,attributes",role="primary"] +.Annotation +---- +@AutoConfigureStubRunner( +stubsMode = StubRunnerProperties.StubsMode.REMOTE, + repositoryRoot = "stubs://file://location/to/the/contracts/directory", + ids = "com.example:some-producer", + properties="stubs.find-producer=true") +---- + +[source,java,indent=0,subs="verbatim,attributes",role="secondary"] +.JUnit 4 Rule +---- + static Map contractProperties() { + Map map = new HashMap<>(); + map.put("stubs.find-producer", "true"); + return map; + } + +@Rule + public StubRunnerRule rule = new StubRunnerRule() + .downloadStub("com.example:some-producer") + .repoRoot("stubs://file://location/to/the/contracts/directory") + .stubsMode(StubRunnerProperties.StubsMode.REMOTE) + .properties(contractProperties()); +---- + +[source,java,indent=0,subs="verbatim,attributes",role="secondary"] +.JUnit 5 Extension +---- + static Map contractProperties() { + Map map = new HashMap<>(); + map.put("stubs.find-producer", "true"); + return map; + } + +@RegisterExtension + public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() + .downloadStub("com.example:some-producer") + .repoRoot("stubs://file://location/to/the/contracts/directory") + .stubsMode(StubRunnerProperties.StubsMode.REMOTE) + .properties(contractProperties()); +---- +==== + [[features-stub-runner-common]] === Common Properties diff --git a/docs/src/main/asciidoc/howto.adoc b/docs/src/main/asciidoc/howto.adoc index 059a55a9c7..2de28179b4 100644 --- a/docs/src/main/asciidoc/howto.adoc +++ b/docs/src/main/asciidoc/howto.adoc @@ -1432,3 +1432,8 @@ include::{standalone_restdocs_path}/http-server/src/test/java/com/example/fraud/ ==== TIP: You need not specify the output directory for the generated snippets (since version 1.2.0.RELEASE of Spring REST Docs). + +[[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 repo or fetching a JAR, just 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 <> of the documentation. \ No newline at end of file diff --git a/docs/src/main/asciidoc/using.adoc b/docs/src/main/asciidoc/using.adoc index a3e6ddeadf..e02cb12430 100644 --- a/docs/src/main/asciidoc/using.adoc +++ b/docs/src/main/asciidoc/using.adoc @@ -90,7 +90,7 @@ stubsMode = StubRunnerProperties.StubsMode.REMOTE, [source,java,indent=0,subs="verbatim,attributes",role="secondary"] .JUnit 5 Extension ---- -@Rule +@RegisterExtension public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() .downloadStub("com.example","artifact-id", "0.0.1") .repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git") diff --git a/samples/standalone/dsl/http-client/src/test/java/com/example/loan/GoodbyeWorldTests.java b/samples/standalone/dsl/http-client/src/test/java/com/example/loan/GoodbyeWorldTests.java index 93de688655..fe086e3f80 100644 --- a/samples/standalone/dsl/http-client/src/test/java/com/example/loan/GoodbyeWorldTests.java +++ b/samples/standalone/dsl/http-client/src/test/java/com/example/loan/GoodbyeWorldTests.java @@ -38,7 +38,6 @@ import static org.assertj.core.api.Assertions.assertThat; stubsMode = StubRunnerProperties.StubsMode.LOCAL, generateStubs = true) public class GoodbyeWorldTests { - // end::autoconfigure_stubrunner[] @StubRunnerPort("http-server-dsl") diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ResourceResolvingStubDownloader.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ResourceResolvingStubDownloader.java index 392ca3f67c..bb2a22cbda 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ResourceResolvingStubDownloader.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/ResourceResolvingStubDownloader.java @@ -73,7 +73,7 @@ class ResourceResolvingStubDownloader implements StubDownloader { if (log.isDebugEnabled()) { log.debug("For paths " + paths + " found following resources " + resources); } - if (resources.isEmpty()) { + if (resources.isEmpty() && this.stubRunnerOptions.isFailOnNoStubs()) { throw new IllegalStateException("No stubs were found on classpath for [" + config.getGroupId() + ":" + config.getArtifactId() + "]"); }