diff --git a/multi/multi__spring_cloud_contract_faq.html b/multi/multi__spring_cloud_contract_faq.html index 9ea6e3205c..4a78662e54 100644 --- a/multi/multi__spring_cloud_contract_faq.html +++ b/multi/multi__spring_cloud_contract_faq.html @@ -101,8 +101,9 @@ consumer you will break with your local changes.

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 repo.

Example of a pom.xml inside the server folder.

<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 
 	<groupId>com.example</groupId>
@@ -116,14 +117,16 @@ one to one to the contents of the repo.

Example of a <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> - <relativePath /> + <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> - <spring-cloud-contract.version>2.1.1.BUILD-SNAPSHOT</spring-cloud-contract.version> - <spring-cloud-release.version>Greenwich.BUILD-SNAPSHOT</spring-cloud-release.version> + <spring-cloud-contract.version>2.1.1.BUILD-SNAPSHOT + </spring-cloud-contract.version> + <spring-cloud-release.version>Greenwich.BUILD-SNAPSHOT + </spring-cloud-release.version> <excludeBuildFolders>true</excludeBuildFolders> </properties> @@ -210,7 +213,8 @@ one to one to the contents of the repo.

Example of a </project>

As you can see there are no dependencies other than the Spring Cloud Contract Maven Plugin. Those poms are necessary for the consumer side to run mvn clean install -DskipTests to locally install stubs of the producer project.

The pom.xml in the root folder can look like this:

<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://maven.apache.org/POM/4.0.0"
 		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 
@@ -219,7 +223,9 @@ Those poms are necessary for the consumer side to run mvn
 	<version>0.0.1-SNAPSHOT</version>
 
 	<name>Contracts</name>
-	<description>Contains all the Spring Cloud Contracts, well, contracts. JAR used by the producers to generate tests and stubs</description>
+	<description>Contains all the Spring Cloud Contracts, well, contracts. JAR used by the
+		producers to generate tests and stubs
+	</description>
 
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -249,8 +255,8 @@ Those poms are necessary for the consumer side to run mvn
 		</plugins>
 	</build>
 
-</project>

It’s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
-		  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+</project>

It’s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:

<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		  xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
 		  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
 	<id>project</id>
 	<formats>
@@ -281,7 +287,9 @@ of the JAR containing the contracts:

<artifactId>spring-cloud-contract-maven-plugin</artifactId>
 	<configuration>
 		<contractsMode>REMOTE</contractsMode>
-		<contractsRepositoryUrl>http://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl>
+		<contractsRepositoryUrl>
+			http://link/to/your/nexus/or/artifactory/or/sth
+		</contractsRepositoryUrl>
 		<contractDependency>
 			<groupId>com.example.standalone</groupId>
 			<artifactId>contracts</artifactId>
diff --git a/multi/multi__spring_cloud_contract_stub_runner.html b/multi/multi__spring_cloud_contract_stub_runner.html
index 9cbf282af8..25b5631645 100644
--- a/multi/multi__spring_cloud_contract_stub_runner.html
+++ b/multi/multi__spring_cloud_contract_stub_runner.html
@@ -246,7 +246,7 @@ case might be starting WireMock for the given artifact id, on an HTTPs port. Exa
 	}
 }

You can then reuse it via the annotation

@AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/",
-			httpServerStubConfigurer = HttpsForFraudDetection)

Whenever an https port is found, it will take precedence over the http one.

6.3.2 Running stubs

Running using main app

You can set the following options to the main class:

-c, --classifier                Suffix for the jar containing stubs (e.
+		httpServerStubConfigurer = HttpsForFraudDetection)

Whenever an https port is found, it will take precedence over the http one.

6.3.2 Running stubs

Running using main app

You can set the following options to the main class:

-c, --classifier                Suffix for the jar containing stubs (e.
                                   g. 'stubs' if the stub jar would
                                   have a 'stubs' classifier for stubs:
                                   foobar-stubs ). Defaults to 'stubs'
@@ -309,11 +309,20 @@ mappings available for the given server:

["uuid" : "f9152eb9-bf77-4c38-8289-90be7d10d0d7"
 },
 ...
-]

Messaging Stubs

Depending on the provided Stub Runner dependency and the DSL the messaging routes are automatically set up.

6.4 Stub Runner JUnit Rule and Stub Runner JUnit5 Extension

Stub Runner comes with a JUnit rule thanks to which you can very easily download and run stubs for given group and artifact id:

@ClassRule public static StubRunnerRule rule = new StubRunnerRule()
-		.repoRoot(repoRoot())
+]

Messaging Stubs

Depending on the provided Stub Runner dependency and the DSL the messaging routes are automatically set up.

6.4 Stub Runner JUnit Rule and Stub Runner JUnit5 Extension

Stub Runner comes with a JUnit rule thanks to which you can very easily download and run stubs for given group and artifact id:

@ClassRule
+public static StubRunnerRule rule = new StubRunnerRule().repoRoot(repoRoot())
 		.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
-		.downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")
-		.downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer");

There’s also a StubRunnerExtension available for JUnit 5. StubRunnerRule and StubRunnerExtension work in a very + .downloadStub("org.springframework.cloud.contract.verifier.stubs", + "loanIssuance") + .downloadStub( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"); + +@BeforeClass +@AfterClass +public static void setupProps() { + System.clearProperty("stubrunner.repository.root"); + System.clearProperty("stubrunner.classifier"); +}

There’s also a StubRunnerExtension available for JUnit 5. StubRunnerRule and StubRunnerExtension work in a very similar fashion. After the rule/ extension is executed, Stub Runner connects to your Maven repository and for the given list of dependencies tries to:

Stub Runner uses Eclipse Aether mechanism to download the Maven dependencies. Check their docs for more information.

Since the StubRunnerRule and StubRunnerExtension implement the StubFinder they allow you to find the started stubs:

package org.springframework.cloud.contract.stubrunner;
 
@@ -323,6 +332,11 @@ Check their import org.springframework.cloud.contract.spec.Contract;
 
+/**
+ * Contract for finding registered stubs.
+ *
+ * @author Marcin Grzejszczak
+ */
 public interface StubFinder extends StubTrigger {
 
 	/**
@@ -330,7 +344,9 @@ Check their 
 	URL findStubUrl(String groupId, String artifactId) throws StubNotFoundException;
 
@@ -340,20 +356,23 @@ Check their 
 	URL findStubUrl(String ivyNotation) throws StubNotFoundException;
 
 	/**
-	 * Returns all running stubs
+	 * @return all running stubs
 	 */
 	RunningStubs findAllRunningStubs();
 
 	/**
-	 * Returns the list of Contracts
+	 * @return the list of Contracts
 	 */
 	Map<StubConfiguration, Collection<Contract>> getContracts();
 
-}

Example of usage in Spock tests:

@ClassRule @Shared StubRunnerRule rule = new StubRunnerRule()
+}

Example of usage in Spock tests:

@ClassRule
+@Shared
+StubRunnerRule rule = new StubRunnerRule()
 		.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
 		.repoRoot(StubRunnerRuleSpec.getResource("/m2repo/repository").toURI().toString())
 		.downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")
@@ -381,64 +400,104 @@ def 'should outp
 		def url = rule.findStubUrl('fraudDetectionServer')
 	then:
 		new File("target/outputmappingsforrule", "fraudDetectionServer_${url.port}").exists()
-}

Example of usage in JUnit tests:

@Test
-public void should_start_wiremock_servers() throws Exception {
-	// expect: 'WireMocks are running'
-		then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")).isNotNull();
+}

Example of usage in JUnit tests:

	@Test
+	public void should_start_wiremock_servers() throws Exception {
+		// expect: 'WireMocks are running'
+		then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs",
+				"loanIssuance")).isNotNull();
 		then(rule.findStubUrl("loanIssuance")).isNotNull();
-		then(rule.findStubUrl("loanIssuance")).isEqualTo(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance"));
-		then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isNotNull();
-	// and:
+		then(rule.findStubUrl("loanIssuance")).isEqualTo(rule.findStubUrl(
+				"org.springframework.cloud.contract.verifier.stubs", "loanIssuance"));
+		then(rule.findStubUrl(
+				"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"))
+						.isNotNull();
+		// and:
 		then(rule.findAllRunningStubs().isPresent("loanIssuance")).isTrue();
-		then(rule.findAllRunningStubs().isPresent("org.springframework.cloud.contract.verifier.stubs", "fraudDetectionServer")).isTrue();
-		then(rule.findAllRunningStubs().isPresent("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isTrue();
-	// and: 'Stubs were registered'
-		then(httpGet(rule.findStubUrl("loanIssuance").toString() + "/name")).isEqualTo("loanIssuance");
-		then(httpGet(rule.findStubUrl("fraudDetectionServer").toString() + "/name")).isEqualTo("fraudDetectionServer");
+		then(rule.findAllRunningStubs().isPresent(
+				"org.springframework.cloud.contract.verifier.stubs",
+				"fraudDetectionServer")).isTrue();
+		then(rule.findAllRunningStubs().isPresent(
+				"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"))
+						.isTrue();
+		// and: 'Stubs were registered'
+		then(httpGet(rule.findStubUrl("loanIssuance").toString() + "/name"))
+				.isEqualTo("loanIssuance");
+		then(httpGet(rule.findStubUrl("fraudDetectionServer").toString() + "/name"))
+				.isEqualTo("fraudDetectionServer");
+	}
+
+	private String httpGet(String url) throws Exception {
+		try (InputStream stream = URI.create(url).toURL().openStream()) {
+			return StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
+		}
+	}
+
 }

JUnit 5 Extension example:

// Visible for Junit
 @RegisterExtension
 static StubRunnerExtension stubRunnerExtension = new StubRunnerExtension()
-        .repoRoot(repoRoot())
-        .stubsMode(StubRunnerProperties.StubsMode.REMOTE)
-        .downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")
-        .downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")
-        .withMappingsOutputFolder("target/outputmappingsforrule");
+		.repoRoot(repoRoot()).stubsMode(StubRunnerProperties.StubsMode.REMOTE)
+		.downloadStub("org.springframework.cloud.contract.verifier.stubs",
+				"loanIssuance")
+		.downloadStub(
+				"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")
+		.withMappingsOutputFolder("target/outputmappingsforrule");
 
-@Test
-void should_start_WireMock_servers() {
-    assertThat(stubRunnerExtension.findStubUrl("org.springframework.cloud.contract.verifier.stubs",
-            "loanIssuance")).isNotNull();
-    assertThat(stubRunnerExtension.findStubUrl("loanIssuance")).isNotNull();
-    assertThat(stubRunnerExtension.findStubUrl("loanIssuance")).isEqualTo(stubRunnerExtension
-            .findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance"));
-    assertThat(stubRunnerExtension
-            .findStubUrl("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isNotNull();
+@BeforeAll
+@AfterAll
+static void setupProps() {
+	System.clearProperty("stubrunner.repository.root");
+	System.clearProperty("stubrunner.classifier");
+}
+
+private static String repoRoot() {
+	try {
+		return StubRunnerRuleJUnitTest.class.getResource("/m2repo/repository/")
+				.toURI().toString();
+	}
+	catch (Exception e) {
+		return "";
+	}
 }

Check the Common properties for JUnit and Spring for more information on how to apply global configuration of Stub Runner.

[Important]Important

To use the JUnit rule or JUnit 5 extension together with messaging, you have to provide an implementation of the MessageVerifier interface to the rule builder (e.g. rule.messageVerifier(new MyMessageVerifier())). If you don’t do this, then whenever you try to send a message an exception will be thrown.

6.4.1 Maven settings

The stub downloader honors Maven settings for a different local repository folder. Authentication details for repositories and profiles are currently not taken into account, so you need to specify it using the properties mentioned above.

6.4.2 Providing fixed ports

You can also run your stubs on fixed ports. You can do it in two different ways. One is to pass it in the properties, and the other via fluent API of -JUnit rule.

6.4.3 Fluent API

When using the StubRunnerRule or StubRunnerExtension you can add a stub to download and then pass the port for the last downloaded stub.

@ClassRule public static StubRunnerRule rule = new StubRunnerRule()
-		.repoRoot(repoRoot())
+JUnit rule.

6.4.3 Fluent API

When using the StubRunnerRule or StubRunnerExtension you can add a stub to download and then pass the port for the last downloaded stub.

@ClassRule
+public static StubRunnerRule rule = new StubRunnerRule().repoRoot(repoRoot())
 		.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
-		.downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")
-		.withPort(12345)
-		.downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:12346");

You can see that for this example the following test is valid:

then(rule.findStubUrl("loanIssuance")).isEqualTo(URI.create("http://localhost:12345").toURL());
-then(rule.findStubUrl("fraudDetectionServer")).isEqualTo(URI.create("http://localhost:12346").toURL());

6.4.4 Stub Runner with Spring

Sets up Spring configuration of the Stub Runner project.

By providing a list of stubs inside your configuration file the Stub Runner automatically downloads + .downloadStub("org.springframework.cloud.contract.verifier.stubs", + "loanIssuance") + .withPort(12345).downloadStub( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:12346"); + +@BeforeClass +@AfterClass +public static void setupProps() { + System.clearProperty("stubrunner.repository.root"); + System.clearProperty("stubrunner.classifier"); +}

You can see that for this example the following test is valid:

then(rule.findStubUrl("loanIssuance"))
+		.isEqualTo(URI.create("http://localhost:12345").toURL());
+then(rule.findStubUrl("fraudDetectionServer"))
+		.isEqualTo(URI.create("http://localhost:12346").toURL());

6.4.4 Stub Runner with Spring

Sets up Spring configuration of the Stub Runner project.

By providing a list of stubs inside your configuration file the Stub Runner automatically downloads and registers in WireMock the selected stubs.

If you want to find the URL of your stubbed dependency you can autowire the StubFinder interface and use its methods as presented below:

@ContextConfiguration(classes = Config, loader = SpringBootContextLoader)
 @SpringBootTest(properties = [" stubrunner.cloud.enabled=false",
 		'foo=${stubrunner.runningstubs.fraudDetectionServer.port}',
 		'fooWithGroup=${stubrunner.runningstubs.org.springframework.cloud.contract.verifier.stubs.fraudDetectionServer.port}'])
 @AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/",
-			httpServerStubConfigurer = HttpsForFraudDetection)
+		httpServerStubConfigurer = HttpsForFraudDetection)
 @ActiveProfiles("test")
 class StubRunnerConfigurationSpec extends Specification {
 
-	@Autowired StubFinder stubFinder
-	@Autowired Environment environment
-	@StubRunnerPort("fraudDetectionServer") int fraudDetectionServerPort
-	@StubRunnerPort("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer") int fraudDetectionServerPortWithGroupId
-	@Value('${foo}') Integer foo
+	@Autowired
+	StubFinder stubFinder
+	@Autowired
+	Environment environment
+	@StubRunnerPort("fraudDetectionServer")
+	int fraudDetectionServerPort
+	@StubRunnerPort("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")
+	int fraudDetectionServerPortWithGroupId
+	@Value('${foo}')
+	Integer foo
 
 	@BeforeClass
 	@AfterClass
@@ -536,8 +595,7 @@ its methods as presented below:

return httpStubConfiguration
 		}
 	}
-}
-// end::test[]

for the following configuration file:

stubrunner:
+}

for the following configuration file:

stubrunner:
   repositoryRoot: classpath:m2repo/repository/
   ids:
     - org.springframework.cloud.contract.verifier.stubs:loanIssuance
@@ -546,8 +604,8 @@ its methods as presented below:

@AutoConfigureStubRunner.
 Below you can find an example of achieving the same result by setting values on the annotation.

@AutoConfigureStubRunner(
 		ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance",
-		"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer",
-		"org.springframework.cloud.contract.verifier.stubs:bootService"],
+				"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer",
+				"org.springframework.cloud.contract.verifier.stubs:bootService"],
 		stubsMode = StubRunnerProperties.StubsMode.REMOTE,
 		repositoryRoot = "classpath:m2repo/repository/")

Stub Runner Spring registers environment variables in the following manner for every registered WireMock server. Example for Stub Runner ids @@ -568,8 +626,7 @@ or DiscoveryClient directly, to call those stubbed }

for the following configuration file

stubrunner:
   idsToServiceIds:
     ivyNotation: someValueInsideYourCode
-    fraudDetectionServer: someNameThatShouldMapFraudDetectionServer
-# end::ids[]

Test profiles and service discovery

In your integration tests you typically don’t want to call neither a discovery service (e.g. Eureka) + fraudDetectionServer: someNameThatShouldMapFraudDetectionServer

Test profiles and service discovery

In your integration tests you typically don’t want to call neither a discovery service (e.g. Eureka) or Config Server. That’s why you create an additional test configuration in which you want to disable these features.

Due to certain limitations of spring-cloud-commons to achieve this you have disable these properties via a static block like presented below (example for Eureka)

    //Hack to work around https://github.com/spring-cloud/spring-cloud-commons/issues/156
@@ -600,7 +657,8 @@ the Stub Runner server. It will be available at port 8750<
 @ActiveProfiles("test")
 class StubRunnerBootSpec extends Specification {
 
-	@Autowired StubRunning stubRunning
+	@Autowired
+	StubRunning stubRunning
 
 	def setup() {
 		RestAssuredMockMvc.standaloneSetup(new HttpStubsController(stubRunning),
@@ -641,7 +699,7 @@ the Stub Runner server. It will be available at port 8750<
 			String response = RestAssuredMockMvc.get('/triggers').body.asString()
 		then:
 			def root = new JsonSlurper().parseText(response)
-			root.'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'?.containsAll(["delete_book","return_book_1","return_book_2"])
+			root.'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'?.containsAll(["delete_book", "return_book_1", "return_book_2"])
 	}
 
 	def 'should trigger a messaging label'() {
@@ -703,15 +761,17 @@ the Stub Runner server. It will be available at port 8750<
 }

As you can see we want to start a Stub Runner Boot server @EnableStubRunnerServer, enable Eureka client @EnableEurekaClient and we want to have the stub runner feature turned on @AutoConfigureStubRunner.

Now let’s assume that we want to start this application so that the stubs get automatically registered. We can do it by running the app java -jar ${SYSTEM_PROPS} stub-runner-boot-eureka-example.jar where - ${SYSTEM_PROPS} would contain the following list of properties

-Dstubrunner.repositoryRoot=http://repo.spring.io/snapshots (1)
--Dstubrunner.cloud.stubbed.discovery.enabled=false (2)
--Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.cloud.contract.verifier.stubs:bootService (3)
--Dstubrunner.idsToServiceIds.fraudDetectionServer=someNameThatShouldMapFraudDetectionServer (4)
-
-(1) - we tell Stub Runner where all the stubs reside
-(2) - we don't want the default behaviour where the discovery service is stubbed. That's why the stub registration will be picked
-(3) - we provide a list of stubs to download
-(4) - we provide a list of artifactId to serviceId mapping

That way your deployed application can send requests to started WireMock servers via the service + ${SYSTEM_PROPS} would contain the following list of properties

* -Dstubrunner.repositoryRoot=http://repo.spring.io/snapshots (1)
+* -Dstubrunner.cloud.stubbed.discovery.enabled=false (2)
+* -Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.
+* springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.
+* cloud.contract.verifier.stubs:bootService (3)
+* -Dstubrunner.idsToServiceIds.fraudDetectionServer=
+* someNameThatShouldMapFraudDetectionServer (4)
+*
+* (1) - we tell Stub Runner where all the stubs reside (2) - we don't want the default
+* behaviour where the discovery service is stubbed. That's why the stub registration will
+* be picked (3) - we provide a list of stubs to download (4) - we provide a list of

That way your deployed application can send requests to started WireMock servers via the service discovery. Most likely points 1-3 could be set by default in application.yml cause they are not likely to change. That way you can provide only the list of stubs to download whenever you start the Stub Runner Boot.

6.7 Stubs Per Consumer

There are cases in which 2 consumers of the same endpoint want to have 2 different responses.

[Tip]Tip

This approach also allows you to immediately know which consumer is using which part of your API. diff --git a/multi/multi__spring_cloud_contract_verifier_introduction.html b/multi/multi__spring_cloud_contract_verifier_introduction.html index 5b366a5a1b..3f64d7c545 100644 --- a/multi/multi__spring_cloud_contract_verifier_introduction.html +++ b/multi/multi__spring_cloud_contract_verifier_introduction.html @@ -120,19 +120,19 @@ org.springframework.cloud.contract.spec.Contract.make { "rejection.reason": "Amount too high" headers: Content-Type: application/json;charset=UTF-8

In the case of messaging, you can define:

  • The input and the output messages can be defined (taking into account from and where it -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:

def contractDsl = Contract.make {
-	label 'some_label'
-	input {
-		messageFrom('jms:delete')
-		messageBody([
-				bookName: 'foo'
-		])
-		messageHeaders {
-			header('sample', 'header')
-		}
-		assertThat('bookWasDeleted()')
-	}
-}

The following example shows the same contract expressed in YAML:

label: some_label
+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:

    			def contractDsl = Contract.make {
    +				label 'some_label'
    +				input {
    +					messageFrom('jms:delete')
    +					messageBody([
    +							bookName: 'foo'
    +					])
    +					messageHeaders {
    +						header('sample', 'header')
    +					}
    +					assertThat('bookWasDeleted()')
    +				}
    +			}

    The following example shows the same contract expressed in YAML:

    label: some_label
     input:
       messageFrom: jms:delete
       messageBody:
    @@ -262,7 +262,23 @@ to the following in the build logs:

    package contracts
    +

    /*
    + * Copyright 2013-2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package contracts
     
     org.springframework.cloud.contract.spec.Contract.make {
     	request { // (1)
    @@ -270,7 +286,7 @@ org.springframework.cloud.contract.spec.Contract.make {
     		url '/fraudcheck' // (3)
     		body([ // (4)
     			   "client.id": $(regex('[0-9]{10}')),
    -			   loanAmount: 99999
    +			   loanAmount : 99999
     		])
     		headers { // (5)
     			contentType('application/json')
    @@ -279,7 +295,7 @@ org.springframework.cloud.contract.spec.Contract.make {
     	response { // (6)
     		status OK() // (7)
     		body([ // (8)
    -			   fraudCheckStatus: "FRAUD",
    +			   fraudCheckStatus  : "FRAUD",
     			   "rejection.reason": "Amount too high"
     		])
     		headers { // (9)
    @@ -374,13 +390,12 @@ response: # (7)
     #(10) - with header `Content-Type` equal to `application/json;charset=UTF-8`

    2.4.4 Client Side

    Spring Cloud Contract generates stubs, which you can use during client-side testing. You get a running WireMock instance/Messaging route that simulates the service. -You would like to feed that instance with a proper stub definition.

    At some point in time, you need to send a request to the Fraud Detection service.

    ResponseEntity<FraudServiceResponse> response =
    -		restTemplate.exchange("http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
    -				new HttpEntity<>(request, httpHeaders),
    -				FraudServiceResponse.class);

    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.

    @RunWith(SpringRunner.class)
    +You would like to feed that instance with a proper stub definition.

    At some point in time, you need to send a request to the Fraud Detection service.

    ResponseEntity<FraudServiceResponse> response = restTemplate.exchange(
    +		"http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
    +		new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class);

    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.

    @RunWith(SpringRunner.class)
     @SpringBootTest(webEnvironment = WebEnvironment.NONE)
    -@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
    -		stubsMode = StubRunnerProperties.StubsMode.LOCAL)
    +@AutoConfigureStubRunner(ids = {
    +		"com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
     public class LoanApplicationServiceTests {

    After that, during the tests, Spring Cloud Contract automatically finds the stubs (simulating the real service) in the Maven repository and exposes them on a configured (or random) port.

    2.4.5 Server Side

    Since you are developing your stub, you need to be sure that it actually resembles your @@ -489,16 +504,31 @@ following section to your build:

    Maven.  }

    Assume that you have written a test of your new feature. If a loan application for a big amount is received, the system should reject that loan application with some description.

    Write the missing implementation.

    At some point in time, you need to send a request to the Fraud Detection service. Assume that you need to send the request containing the ID of the client and the amount the -client wants to borrow. You want to send it to the /fraudcheck url via the PUT method.

    ResponseEntity<FraudServiceResponse> response =
    -		restTemplate.exchange("http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
    -				new HttpEntity<>(request, httpHeaders),
    -				FraudServiceResponse.class);

    For simplicity, the port of the Fraud Detection service is set to 8080, and the +client wants to borrow. You want to send it to the /fraudcheck url via the PUT method.

    ResponseEntity<FraudServiceResponse> response = restTemplate.exchange(
    +		"http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
    +		new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class);

    For simplicity, the port of the Fraud Detection service is set to 8080, and the application runs on 8090.

    If you start the test at this point, it breaks, because no service currently runs on port 8080.

    Clone the Fraud Detection service repository locally.

    You can start by playing around with the server side contract. To do so, you must first clone it.

    $ git clone https://your-git-server.com/server-side.git local-http-server-repo

    Define the contract locally in the repo of Fraud Detection service.

    As a consumer, you need to define what exactly you want to achieve. You need to formulate your expectations. To do so, write the following contract:

    [Important]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.  -

    package contracts
    +

    /*
    + * Copyright 2013-2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package contracts
     
     org.springframework.cloud.contract.spec.Contract.make {
     	request { // (1)
    @@ -506,7 +536,7 @@ org.springframework.cloud.contract.spec.Contract.make {
     		url '/fraudcheck' // (3)
     		body([ // (4)
     			   "client.id": $(regex('[0-9]{10}')),
    -			   loanAmount: 99999
    +			   loanAmount : 99999
     		])
     		headers { // (5)
     			contentType('application/json')
    @@ -515,7 +545,7 @@ org.springframework.cloud.contract.spec.Contract.make {
     	response { // (6)
     		status OK() // (7)
     		body([ // (8)
    -			   fraudCheckStatus: "FRAUD",
    +			   fraudCheckStatus  : "FRAUD",
     			   "rejection.reason": "Amount too high"
     		])
     		headers { // (9)
    @@ -676,8 +706,8 @@ Application service):

    Add the Spring Cloud Co collaborators. (Optional step) Because you’re playing with the collaborators offline, you can also provide the offline work switch (StubRunnerProperties.StubsMode.LOCAL).

    @RunWith(SpringRunner.class)
     @SpringBootTest(webEnvironment = WebEnvironment.NONE)
    -@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
    -		stubsMode = StubRunnerProperties.StubsMode.LOCAL)
    +@AutoConfigureStubRunner(ids = {
    +		"com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
     public class LoanApplicationServiceTests {

    Now, when you run your tests, you see something like this:

    2016-07-19 14:22:25.403  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is + - will try to resolve the latest version
     2016-07-19 14:22:25.438  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is 0.0.1-SNAPSHOT
     2016-07-19 14:22:25.439  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact com.example:http-server:jar:stubs:0.0.1-SNAPSHOT using remote repositories []
    @@ -713,12 +743,29 @@ make the name of the base test class. In our case, the contracts were placed und
     the contracts folder, pick only one, which should be fraud. Add the Base suffix and
     capitalize fraud. That gives you the FraudBase test class name.

    All the generated tests extend that class. Over there, you can set up your Spring Context or whatever is necessary. In this case, use Rest Assured MVC to -start the server side FraudDetectionController.

    package com.example.fraud;
    +start the server side FraudDetectionController.

    /*
    + * Copyright 2013-2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package com.example.fraud;
     
     import io.restassured.module.mockmvc.RestAssuredMockMvc;
     import org.junit.Before;
     
     public class FraudBase {
    +
     	@Before
     	public void setup() {
     		RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(),
    @@ -740,6 +787,7 @@ start the server side FraudDetectionController.

    public void assertThatRejectionReasonIsNull(Object rejectionReason) { assert rejectionReason == null; } + }

    Now, if you run the ./mvnw clean install, you get something like this:

    Results :
     
     Tests in error:
    diff --git a/multi/multi__spring_cloud_contract_verifier_messaging.html b/multi/multi__spring_cloud_contract_verifier_messaging.html
    index ac737623be..bc9cf3db58 100644
    --- a/multi/multi__spring_cloud_contract_verifier_messaging.html
    +++ b/multi/multi__spring_cloud_contract_verifier_messaging.html
    @@ -36,20 +36,20 @@ meanings for different messaging implementations. For destination of a channel. Then, if there is no such destination
     it is resolved as a channel name. For Camel, that’s a certain component (for example,
     jms).

    5.3.1 Scenario 1: No Input Message

    For the given contract:

    Groovy DSL.  -

    def contractDsl = Contract.make {
    -	label 'some_label'
    -	input {
    -		triggeredBy('bookReturnedTriggered()')
    -	}
    -	outputMessage {
    -		sentTo('activemq:output')
    -		body('''{ "bookName" : "foo" }''')
    -		headers {
    -			header('BOOK-NAME', 'foo')
    -			messagingContentType(applicationJson())
    -		}
    -	}
    -}

    +

    			def contractDsl = Contract.make {
    +				label 'some_label'
    +				input {
    +					triggeredBy('bookReturnedTriggered()')
    +				}
    +				outputMessage {
    +					sentTo('activemq:output')
    +					body('''{ "bookName" : "foo" }''')
    +					headers {
    +						header('BOOK-NAME', 'foo')
    +						messagingContentType(applicationJson())
    +					}
    +				}
    +			}

    YAML. 

    label: some_label
     input:
    @@ -61,7 +61,7 @@ outputMessage:
       headers:
         BOOK-NAME: foo
         contentType: application/json

    -

    The following JUnit test is created:

    '''
    +

    The following JUnit test is created:

    					'''
      // when:
       bookReturnedTriggered();
     
    @@ -75,7 +75,7 @@ outputMessage:
      // and:
       DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
       assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
    -'''

    And the following Spock test would be created:

    '''
    +'''

    And the following Spock test would be created:

    					'''
      when:
       bookReturnedTriggered()
     
    @@ -89,27 +89,27 @@ outputMessage:
       assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
     
     '''

    5.3.2 Scenario 2: Output Triggered by Input

    For the given contract:

    Groovy DSL.  -

    def contractDsl = Contract.make {
    -	label 'some_label'
    -	input {
    -		messageFrom('jms:input')
    -		messageBody([
    -				bookName: 'foo'
    -		])
    -		messageHeaders {
    -			header('sample', 'header')
    -		}
    -	}
    -	outputMessage {
    -		sentTo('jms:output')
    -		body([
    -				bookName: 'foo'
    -		])
    -		headers {
    -			header('BOOK-NAME', 'foo')
    -		}
    -	}
    -}

    +

    			def contractDsl = Contract.make {
    +				label 'some_label'
    +				input {
    +					messageFrom('jms:input')
    +					messageBody([
    +							bookName: 'foo'
    +					])
    +					messageHeaders {
    +						header('sample', 'header')
    +					}
    +				}
    +				outputMessage {
    +					sentTo('jms:output')
    +					body([
    +							bookName: 'foo'
    +					])
    +					headers {
    +						header('BOOK-NAME', 'foo')
    +					}
    +				}
    +			}

    YAML. 

    label: some_label
     input:
    @@ -124,7 +124,7 @@ outputMessage:
         bookName: foo
       headers:
         BOOK-NAME: foo

    -

    The following JUnit test is created:

    '''
    +

    The following JUnit test is created:

    					'''
     // given:
      ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
       "{\\"bookName\\":\\"foo\\"}"
    @@ -142,7 +142,7 @@ outputMessage:
     // and:
      DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
      assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
    -'''

    And the following Spock test would be created:

    """\
    +'''

    And the following Spock test would be created:

    					"""\
     given:
        ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
         '''{"bookName":"foo"}''',
    @@ -160,19 +160,19 @@ and:
        DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
        assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
     """

    5.3.3 Scenario 3: No Output Message

    For the given contract:

    Groovy DSL.  -

    def contractDsl = Contract.make {
    -	label 'some_label'
    -	input {
    -		messageFrom('jms:delete')
    -		messageBody([
    -				bookName: 'foo'
    -		])
    -		messageHeaders {
    -			header('sample', 'header')
    -		}
    -		assertThat('bookWasDeleted()')
    -	}
    -}

    +

    			def contractDsl = Contract.make {
    +				label 'some_label'
    +				input {
    +					messageFrom('jms:delete')
    +					messageBody([
    +							bookName: 'foo'
    +					])
    +					messageHeaders {
    +						header('sample', 'header')
    +					}
    +					assertThat('bookWasDeleted()')
    +				}
    +			}

    YAML. 

    label: some_label
     input:
    @@ -182,7 +182,7 @@ input:
       messageHeaders:
         sample: header
       assertThat: bookWasDeleted()

    -

    The following JUnit test is created:

    '''
    +

    The following JUnit test is created:

    					'''
     // given:
      ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
     	"{\\"bookName\\":\\"foo\\"}"
    @@ -194,7 +194,7 @@ input:
     
     // then:
      bookWasDeleted();
    -'''

    And the following Spock test would be created:

    '''
    +'''

    And the following Spock test would be created:

    					'''
     given:
     	 ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
     		\'\'\'{"bookName":"foo"}\'\'\',
    diff --git a/multi/multi__spring_cloud_contract_verifier_setup.html b/multi/multi__spring_cloud_contract_verifier_setup.html
    index 3fa864e5c5..b3c33f9f6a 100644
    --- a/multi/multi__spring_cloud_contract_verifier_setup.html
    +++ b/multi/multi__spring_cloud_contract_verifier_setup.html
    @@ -176,7 +176,7 @@ name of the base class for the matched contract. You have to provide a list call
     contractPackageRegex to baseClassFQN mapping. Consider the following example:

    baseClassForTests = "com.example.FooBase"
     baseClassMappings {
     	baseClassMapping('.*/com/.*', 'com.example.ComBase')
    -	baseClassMapping('.*/bar/.*':'com.example.BarBase')
    +	baseClassMapping('.*/bar/.*': 'com.example.BarBase')
     }

    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. diff --git a/multi/multi__spring_cloud_contract_wiremock.html b/multi/multi__spring_cloud_contract_wiremock.html index e9dff9d7a7..df973217a4 100644 --- a/multi/multi__spring_cloud_contract_wiremock.html +++ b/multi/multi__spring_cloud_contract_wiremock.html @@ -17,6 +17,12 @@ your test. The following code shows an example:

    <
     	@Autowired
     	private Service service;
     
    +	@Before
    +	public void setup() {
    +		this.service.setBase("http://localhost:"
    +				+ this.environment.getProperty("wiremock.server.port"));
    +	}
    +
     	// Using the WireMock APIs in the normal way:
     	@Test
     	public void contextLoads() throws Exception {
    @@ -27,8 +33,7 @@ your test. The following code shows an example:

    <
     		assertThat(this.service.go()).isEqualTo("Hello World!");
     	}
     
    -}
    -// end::wiremock_test2[]

    To start the stub server on a different port use (for example), +}

    To start the stub server on a different port use (for example), @AutoConfigureWireMock(port=9999). For a random port, use a value of 0. The stub server port can be bound in the test application context with the "wiremock.server.port" property. Using @AutoConfigureWireMock adds a bean of type WiremockConfiguration to @@ -76,15 +81,15 @@ instance, as shown in the following example:

    
     	public static WireMockClassRule wiremock = new WireMockClassRule(
     			WireMockSpring.options().dynamicPort());
     
    +	// A service that calls out over HTTP to wiremock's port
    +	@Autowired
    +	private Service service;
    +
     	@Before
     	public void setup() {
     		this.service.setBase("http://localhost:" + wiremock.port());
     	}
     
    -	// A service that calls out over HTTP to wiremock's port
    -	@Autowired
    -	private Service service;
    -
     	// Using the WireMock APIs in the normal way:
     	@Test
     	public void contextLoads() throws Exception {
    @@ -95,8 +100,7 @@ instance, as shown in the following example:

    
     		assertThat(this.service.go()).isEqualTo("Hello World!");
     	}
     
    -}
    -// end::wiremock_test2[]

    The @ClassRule means that the server shuts down after all the methods in this class +}

    The @ClassRule means that the server shuts down after all the methods in this class have been run.

    11.4 Relaxed SSL Validation for Rest Template

    WireMock lets you stub a "secure" server with an "https" URL protocol. If your application wants to contact that stub server in an integration test, it will find that the SSL certificates are not valid (the usual problem with self-installed certificates). diff --git a/multi/multi__using_the_pluggable_architecture.html b/multi/multi__using_the_pluggable_architecture.html index 115ece5542..aaeb73feeb 100644 --- a/multi/multi__using_the_pluggable_architecture.html +++ b/multi/multi__using_the_pluggable_architecture.html @@ -12,7 +12,7 @@ structure converter. The following code listing shows the * Converter to be used to convert FROM {@link File} TO {@link Contract} * and from {@link Contract} to {@code T} * - * @param <T> - type to which we want to convert the contract + * @param <T > - type to which we want to convert the contract * * @author Marcin Grzejszczak * @since 1.1.0 @@ -98,7 +98,7 @@ set a metaData entry in the Pact file, with key "combine": "AND" } }, - "body" : { + "body": { "$.clientId": { "matchers": [ { @@ -233,15 +233,31 @@ current Pact version that you use.

    Maven. 

    testCompile "org.springframework.cloud:spring-cloud-contract-pact"

    10.2 Using the Custom Test Generator

    If you want to generate tests for languages other than Java or you are not happy with the way the verifier builds Java tests, you can register your own implementation.

    The SingleTestGenerator interface lets you register your own implementation. The -following code listing shows the SingleTestGenerator interface:

    	 *
    -	 * @param properties                    - properties passed to the plugin
    -	 * @param listOfFiles                   - list of parsed contracts with additional metadata
    -	 * @param className                     - the name of the generated test class
    -	 * @param classPackage                  - the name of the package in which the test class should be stored
    -	 * @param includedDirectoryRelativePath - relative path to the included directory
    -	 * @return contents of a single test class
    -	 * @deprecated use {@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)}
    -	 */
    +following code listing shows the SingleTestGenerator interface:

    package org.springframework.cloud.contract.verifier.builder
    +
    +
    +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
    +import org.springframework.cloud.contract.verifier.file.ContractMetadata
    +
    +/**
    + * Builds a single test.
    + *
    + * @since 1.1.0
    + */
    +trait SingleTestGenerator {
    +
    +	/**
    +	 * Creates contents of a single test class in which all test scenarios from
    +	 * the contract metadata should be placed.
    +	 *
    +	 * @param properties - properties passed to the plugin
    +	 * @param listOfFiles - list of parsed contracts with additional metadata
    +	 * @param className - the name of the generated test class
    +	 * @param classPackage - the name of the package in which the test class should be stored
    +	 * @param includedDirectoryRelativePath - relative path to the included directory
    +	 * @return contents of a single test class
    +	 * @deprecated use{@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)}
    +	 */
     	@Deprecated
     	abstract String buildClass(ContractVerifierConfigProperties properties,
     			Collection<ContractMetadata> listOfFiles, String className, String classPackage, String includedDirectoryRelativePath)
    @@ -250,15 +266,18 @@ following code listing shows the SingleTestGenerator
     	String buildClass(ContractVerifierConfigProperties properties,
     			Collection<ContractMetadata> listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) {
    -		return buildClass(properties, listOfFiles, generatedClassData.className, generatedClassData.classPackage, includedDirectoryRelativePath)
    +		String className = generatedClassData.className
    +		String classPackage = generatedClassData.classPackage
    +		String path = includedDirectoryRelativePath
    +		return buildClass(properties, listOfFiles, className, classPackage, path)
     	}
     
     	/**
    @@ -287,6 +306,7 @@ own implementation of the StubGenerator interface.
     StubGenerator interface:

    package org.springframework.cloud.contract.verifier.converter
     
     import groovy.transform.CompileStatic
    +
     import org.springframework.cloud.contract.spec.Contract
     import org.springframework.cloud.contract.verifier.file.ContractMetadata
     
    @@ -299,18 +319,18 @@ own implementation of the StubGenerator interface.
     interface StubGenerator {
     
     	/**
    -	 * Returns {@code true} if the converter can handle the file to convert it into a stub.
    +	 * @return {@code true} if the converter can handle the file to convert it into a stub.
     	 */
     	boolean canHandleFileName(String fileName)
     
     	/**
    -	 * Returns the collection of converted contracts into stubs. One contract can
    +	 * @return the collection of converted contracts into stubs. One contract can
     	 * result in multiple stubs.
     	 */
     	Map<Contract, String> convertContents(String rootName, ContractMetadata content)
     
     	/**
    -	 * Returns the name of the converted stub file. If you have multiple contracts
    +	 * @return the name of the converted stub file. If you have multiple contracts
     	 * in a single file then a prefix will be added to the generated file. If you
     	 * provide the {@link Contract#name} field then that field will override the
     	 * generated file name.
    @@ -380,17 +400,19 @@ HTTP Stub server implementation, which might resemble the following example:

    @Override HttpServerStub registerMappings(Collection<File> stubFiles) { List<RunnerSetting> settings = stubFiles.findAll { it.name.endsWith("json") } - .collect { + .collect { log.info("Trying to parse [${it.name}]") try { - return RunnerSetting.aRunnerSetting().withStream(it.newInputStream()).build() - } catch (Exception e) { + return RunnerSetting.aRunnerSetting().withStream(it.newInputStream()). + build() + } + catch (Exception e) { log.warn("Exception occurred while trying to parse file [${it.name}]", e) return null } }.findAll { it } this.runner = JsonRunner.newJsonRunnerWithSetting(settings, - HttpArgs.httpArgs().withPort(this.port).build()) + HttpArgs.httpArgs().withPort(this.port).build()) this.runner.run() this.started = true return this diff --git a/multi/multi_contract-dsl.html b/multi/multi_contract-dsl.html index 90d955f9f8..7bd49d9805 100644 --- a/multi/multi_contract-dsl.html +++ b/multi/multi_contract-dsl.html @@ -65,8 +65,8 @@ You can also provide the assertJsonSize property in properly when using the Groovy DSL and the value(consumer(…​), producer(…​)) notation in GString. That is why you should use the Groovy Map notation.

    8.2 Common Top-Level elements

    The following sections describe the most common top-level elements:

    8.2.1 Description

    You can add a description to your contract. The description is arbitrary text. The following code shows an example:

    Groovy DSL.  -

    		org.springframework.cloud.contract.spec.Contract.make {
    -			description('''
    +

    			org.springframework.cloud.contract.spec.Contract.make {
    +				description('''
     given:
     	An input
     when:
    @@ -74,7 +74,7 @@ when:
     then:
     	Output
     ''')
    -		}

    + }

    YAML. 

    description: Some description
     name: some name
    @@ -152,7 +152,23 @@ following resources in our project.

    └─
                     ├── readFromFile.groovy
                     ├── request.json
                     └── response.json

    Further assume that your contract is as follows:

    Groovy DSL.  -

    import org.springframework.cloud.contract.spec.Contract
    +

    /*
    + * Copyright 2013-2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +import org.springframework.cloud.contract.spec.Contract
     
     Contract.make {
     	request {
    @@ -208,16 +224,16 @@ Contract.make {
     }

    YAML. 

    request:
    -    url: /1
    -    method: PUT
    -    headers:
    -        Content-Type: application/octet-stream
    -    bodyFromFileAsBytes: request.pdf
    +  url: /1
    +  method: PUT
    +  headers:
    +    Content-Type: application/octet-stream
    +  bodyFromFileAsBytes: request.pdf
     response:
    -    status: 200
    -    bodyFromFileAsBytes: response.pdf
    -    headers:
    -        Content-Type: application/octet-stream

    + status: 200 + bodyFromFileAsBytes: response.pdf + headers: + Content-Type: application/octet-stream

    [Important]Important

    You should use this approach whenever you want to work with binary payloads both for HTTP and messaging.

    8.2.5 HTTP Top-Level Elements

    The following methods can be called in the top-level closure of a contract definition. request and response are mandatory. priority is optional.

    Groovy DSL. 

    org.springframework.cloud.contract.spec.Contract.make {
    @@ -476,7 +492,7 @@ body:
         Content-Type: multipart/form-data;boundary=AaB03x
       multipart:
         params:
    -    # key (parameter name), value (parameter value) pair
    +      # key (parameter name), value (parameter value) pair
           formParameter: '"formParameterValue"'
           someBooleanParameter: true
         named:
    @@ -610,25 +626,25 @@ need to use patterns and not exact values both for your test and your server sid
     }

    You can also provide only one side of the communication with a regular expression. If you do so, then the contract engine automatically provides the generated string that matches the provided regular expression. The following code shows an example:

    org.springframework.cloud.contract.spec.Contract.make {
    -    request {
    -        method 'PUT'
    -        url value(consumer(regex('/foo/[0-9]{5}')))
    -        body([
    -                requestElement: $(consumer(regex('[0-9]{5}')))
    -        ])
    -        headers {
    -            header('header', $(consumer(regex('application\\/vnd\\.fraud\\.v1\\+json;.*'))))
    -        }
    -    }
    -    response {
    -        status OK()
    -        body([
    -                responseElement: $(producer(regex('[0-9]{7}')))
    -        ])
    -        headers {
    -            contentType("application/vnd.fraud.v1+json")
    -        }
    -    }
    +	request {
    +		method 'PUT'
    +		url value(consumer(regex('/foo/[0-9]{5}')))
    +		body([
    +				requestElement: $(consumer(regex('[0-9]{5}')))
    +		])
    +		headers {
    +			header('header', $(consumer(regex('application\\/vnd\\.fraud\\.v1\\+json;.*'))))
    +		}
    +	}
    +	response {
    +		status OK()
    +		body([
    +				responseElement: $(producer(regex('[0-9]{7}')))
    +		])
    +		headers {
    +			contentType("application/vnd.fraud.v1+json")
    +		}
    +	}
     }

    In the preceding example, the opposite side of the communication has the respective data generated for request and response.

    Spring Cloud Contract comes with a series of predefined regular expressions that you can use in your contracts, as shown in the following example:

    protected static final Pattern TRUE_OR_FALSE = Pattern.compile(/(true|false)/)
    @@ -639,21 +655,29 @@ use in your contracts, as shown in the following example:

    protected static final Pattern POSITIVE_INT = Pattern.compile('([1-9]\\d*)')
     protected static final Pattern DOUBLE = Pattern.compile('-?(\\d*\\.\\d+)')
     protected static final Pattern HEX = Pattern.compile('[a-fA-F0-9]+')
    -protected static final Pattern IP_ADDRESS = Pattern.compile('([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])')
    -protected static final Pattern HOSTNAME_PATTERN = Pattern.compile('((http[s]?|ftp):/)/?([^:/\\s]+)(:[0-9]{1,5})?')
    -protected static final Pattern EMAIL = Pattern.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}')
    +protected static final Pattern IP_ADDRESS = Pattern.
    +		compile('([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])')
    +protected static final Pattern HOSTNAME_PATTERN = Pattern.
    +		compile('((http[s]?|ftp):/)/?([^:/\\s]+)(:[0-9]{1,5})?')
    +protected static final Pattern EMAIL = Pattern.
    +		compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}')
     protected static final Pattern URL = UrlHelper.URL
     protected static final Pattern HTTPS_URL = UrlHelper.HTTPS_URL
    -protected static final Pattern UUID = Pattern.compile('[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}')
    -protected static final Pattern ANY_DATE = Pattern.compile('(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])')
    -protected static final Pattern ANY_DATE_TIME = Pattern.compile('([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])')
    -protected static final Pattern ANY_TIME = Pattern.compile('(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])')
    +protected static final Pattern UUID = Pattern.
    +		compile('[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}')
    +protected static final Pattern ANY_DATE = Pattern.
    +		compile('(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])')
    +protected static final Pattern ANY_DATE_TIME = Pattern.
    +		compile('([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])')
    +protected static final Pattern ANY_TIME = Pattern.
    +		compile('(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])')
     protected static final Pattern NON_EMPTY = Pattern.compile(/[\S\s]+/)
     protected static final Pattern NON_BLANK = Pattern.compile(/^\s*\S[\S\s]*/)
    -protected static final Pattern ISO8601_WITH_OFFSET = Pattern.compile(/([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d{3})?(Z|[+-][01]\d:[0-5]\d)/)
    +protected static final Pattern ISO8601_WITH_OFFSET = Pattern.
    +		compile(/([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d{3})?(Z|[+-][01]\d:[0-5]\d)/)
     
    -protected static Pattern anyOf(String... values){
    -	return Pattern.compile(values.collect({"^$it\$"}).join("|"))
    +protected static Pattern anyOf(String... values) {
    +	return Pattern.compile(values.collect({ "^$it\$" }).join("|"))
     }
     
     RegexProperty onlyAlphaUnicode() {
    @@ -704,7 +728,7 @@ RegexProperty httpsUrl() {
     	return new RegexProperty(HTTPS_URL).asString()
     }
     
    -RegexProperty uuid(){
    +RegexProperty uuid() {
     	return new RegexProperty(UUID).asString()
     }
     
    @@ -731,28 +755,28 @@ RegexProperty nonEmpty() {
     RegexProperty nonBlank() {
     	return new RegexProperty(NON_BLANK).asString()
     }

    In your contract, you can use it as shown in the following example:

    Contract dslWithOptionalsInString = Contract.make {
    -    priority 1
    -    request {
    -        method POST()
    -        url '/users/password'
    -        headers {
    -            contentType(applicationJson())
    -        }
    -        body(
    -                email: $(consumer(optional(regex(email()))), producer('abc@abc.com')),
    -                callback_url: $(consumer(regex(hostname())), producer('http://partners.com'))
    -        )
    -    }
    -    response {
    -        status 404
    -        headers {
    -            contentType(applicationJson())
    -        }
    -        body(
    -                code: value(consumer("123123"), producer(optional("123123"))),
    -                message: "User not found by email = [${value(producer(regex(email())), consumer('not.existing@user.com'))}]"
    -        )
    -    }
    +	priority 1
    +	request {
    +		method POST()
    +		url '/users/password'
    +		headers {
    +			contentType(applicationJson())
    +		}
    +		body(
    +				email: $(consumer(optional(regex(email()))), producer('abc@abc.com')),
    +				callback_url: $(consumer(regex(hostname())), producer('http://partners.com'))
    +		)
    +	}
    +	response {
    +		status 404
    +		headers {
    +			contentType(applicationJson())
    +		}
    +		body(
    +				code: value(consumer("123123"), producer(optional("123123"))),
    +				message: "User not found by email = [${value(producer(regex(email())), consumer('not.existing@user.com'))}]"
    +		)
    +	}
     }

    To make matters even simpler you can use a set of predefined objects that will automatically assume that you want a regular expression to be passed. All of those methods start with any prefix:

    T anyAlphaUnicode()
     
    @@ -802,25 +826,25 @@ T anyOf(String... values)

    and this is an example of how you can referenc outputMessage { sentTo 'topic.rateablequote' body([ - alpha: $(anyAlphaUnicode()), - number: $(anyNumber()), - anInteger: $(anyInteger()), - positiveInt: $(anyPositiveInt()), - aDouble: $(anyDouble()), - aBoolean: $(aBoolean()), - ip: $(anyIpAddress()), - hostname: $(anyHostname()), - email: $(anyEmail()), - url: $(anyUrl()), - httpsUrl: $(anyHttpsUrl()), - uuid: $(anyUuid()), - date: $(anyDate()), - dateTime: $(anyDateTime()), - time: $(anyTime()), + alpha : $(anyAlphaUnicode()), + number : $(anyNumber()), + anInteger : $(anyInteger()), + positiveInt : $(anyPositiveInt()), + aDouble : $(anyDouble()), + aBoolean : $(aBoolean()), + ip : $(anyIpAddress()), + hostname : $(anyHostname()), + email : $(anyEmail()), + url : $(anyUrl()), + httpsUrl : $(anyHttpsUrl()), + uuid : $(anyUuid()), + date : $(anyDate()), + dateTime : $(anyDateTime()), + time : $(anyTime()), iso8601WithOffset: $(anyIso8601WithOffset()), - nonBlankString: $(anyNonBlankString()), - nonEmptyString: $(anyNonEmptyString()), - anyOf: $(anyOf('foo', 'bar')) + nonBlankString : $(anyNonBlankString()), + nonEmptyString : $(anyNonEmptyString()), + anyOf : $(anyOf('foo', 'bar')) ]) } }

    8.5.3 Passing Optional Parameters

    [Important]Important

    This section is valid only for Groovy DSL. Check out the @@ -848,7 +872,7 @@ optional parameters only for the following:

      By wrapping a part of the body with the optional() method, you create a regular -expression that must be present 0 or more times.

      If you use Spock for, the following test would be generated from the previous example:

      """
      +expression that must be present 0 or more times.

      If you use Spock for, the following test would be generated from the previous example:

      					"""
        given:
         def request = given()
           .header("Content-Type", "application/json")
      @@ -864,7 +888,7 @@ expression that must be present 0 or more times.

      If you use Spock for, the and: DocumentContext parsedJson = JsonPath.parse(response.body.asString()) assertThatJson(parsedJson).field("['code']").matches("(123123)?") -"""

      The following stub would also be generated:

      '''
      +"""

      The following stub would also be generated:

      					'''
       {
         "request" : {
       	"url" : "/users/password",
      @@ -900,13 +924,13 @@ following code shows an example of the contract portion of the test case:

      'Content-Type': 'application/json' } body '''\ - [{ - "text": "Gonna see you at Warsaw" - }] - ''' + [{ + "text": "Gonna see you at Warsaw" + }] + ''' } response { - body ( + body( path: $(consumer('/api/12'), producer(regex('^/api/[0-9]{2}$'))), correlationId: $(consumer('1223456'), producer(execute('isProperCorrelationId($it)'))) ) @@ -1076,7 +1100,23 @@ Since we use the spring.factories extension approach, you can create an entry in org.springframework.cloud.contract.stubrunner.provider.wiremock.TestWireMockExtensions org.springframework.cloud.contract.spec.ContractConverter=\ org.springframework.cloud.contract.stubrunner.TestCustomYamlContractConverter

      The following is an example of a custom extension:

      TestWireMockExtensions.groovy.  -

      package org.springframework.cloud.contract.verifier.dsl.wiremock
      +

      /*
      + * Copyright 2013-2019 the original author or authors.
      + *
      + * Licensed under the Apache License, Version 2.0 (the "License");
      + * you may not use this file except in compliance with the License.
      + * You may obtain a copy of the License at
      + *
      + *      http://www.apache.org/licenses/LICENSE-2.0
      + *
      + * Unless required by applicable law or agreed to in writing, software
      + * distributed under the License is distributed on an "AS IS" BASIS,
      + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      + * See the License for the specific language governing permissions and
      + * limitations under the License.
      + */
      +
      +package org.springframework.cloud.contract.verifier.dsl.wiremock
       
       import com.github.tomakehurst.wiremock.extension.Extension
       
      @@ -1399,7 +1439,7 @@ response:
           valueWithMinEmpty: []
           valueWithMaxEmpty: []
           key:
      -      'complex.key' : 'foo'
      +      'complex.key': 'foo'
           nulValue: null
         matchers:
           headers:
      @@ -1513,7 +1553,7 @@ separates the autogenerated assertions and the assertion from matchers):

      assertThatValueIsANumber. This method must be defined in the test base class or be
       statically imported to your tests. Notice that the byCommand call was converted to
       assertThatValueIsANumber(parsedJson.read("$.duck"));. That means that the engine took
      -the method name and passed the proper JSON path as a parameter to it.

    The resulting WireMock stub is in the following example:

    				'''
    +the method name and passed the proper JSON path as a parameter to it.

    The resulting WireMock stub is in the following example:

    					'''
     {
       "request" : {
         "urlPath" : "/get",
    @@ -1614,7 +1654,7 @@ asserted. In order to fix this, you should apply the assertion to the whole byCommand(…​) method.

    8.6 JAX-RS Support

    The Spring Cloud Contract Verifier supports the JAX-RS 2 Client API. The base class needs to define protected WebTarget webTarget and server initialization. The only option for testing JAX-RS API is to start a web server. Also, a request with a body needs to have a -content type set. Otherwise, the default of application/octet-stream gets used.

    In order to use JAX-RS mode, use the following settings:

    testMode == 'JAXRSCLIENT'

    The following example shows a generated test API:

    '''
    +content type set. Otherwise, the default of application/octet-stream gets used.

    In order to use JAX-RS mode, use the following settings:

    testMode == 'JAXRSCLIENT'

    The following example shows a generated test API:

    					'''
      // when:
       Response response = webTarget
         .path("/users")
    @@ -1783,19 +1823,19 @@ as a String or GString
     both request and response. In place of the jsonPath(…​) method, the org.springframework.cloud.contract.spec.internal.BodyMatchers.xPath
     method should be used, with the desired xPath provided as the first argument
     and the appropriate MatchingType as second. All the body matchers apart from byType() are supported.

    Here is an example of a Groovy DSL contract with XML response body:

    					Contract.make {
    -				request {
    -					method GET()
    -					urlPath '/get'
    -					headers {
    -						contentType(applicationXml())
    -					}
    -				}
    -				response {
    -					status(OK())
    -					headers {
    -						contentType(applicationXml())
    -					}
    -					body """
    +						request {
    +							method GET()
    +							urlPath '/get'
    +							headers {
    +								contentType(applicationXml())
    +							}
    +						}
    +						response {
    +							status(OK())
    +							headers {
    +								contentType(applicationXml())
    +							}
    +							body """
     <test>
     <duck type='xtype'>123</duck>
     <alpha>abc</alpha>
    @@ -1812,22 +1852,22 @@ and the appropriate MatchingType as second. All the
     <valueWithoutAMatcher>foo</valueWithoutAMatcher>
     <key><complex>foo</complex></key>
     </test>"""
    -					bodyMatchers {
    -						xPath('/test/duck/text()', byRegex("[0-9]{3}"))
    -						xPath('/test/duck/text()', byCommand('test($it)'))
    -						xPath('/test/duck/xxx', byNull())
    -						xPath('/test/duck/text()', byEquality())
    -						xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode()))
    -						xPath('/test/alpha/text()', byEquality())
    -						xPath('/test/number/text()', byRegex(number()))
    -						xPath('/test/date/text()', byDate())
    -						xPath('/test/dateTime/text()', byTimestamp())
    -						xPath('/test/time/text()', byTime())
    -						xPath('/test/*/complex/text()', byEquality())
    -						xPath('/test/duck/@type', byEquality())
    -					}
    -				}
    -			}

    And below is an example of a YAML contract with XML request and response bodies:

    include::{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml

    Here is an example of an automatically generated test for XML response body:

    @Test
    +							bodyMatchers {
    +								xPath('/test/duck/text()', byRegex("[0-9]{3}"))
    +								xPath('/test/duck/text()', byCommand('test($it)'))
    +								xPath('/test/duck/xxx', byNull())
    +								xPath('/test/duck/text()', byEquality())
    +								xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode()))
    +								xPath('/test/alpha/text()', byEquality())
    +								xPath('/test/number/text()', byRegex(number()))
    +								xPath('/test/date/text()', byDate())
    +								xPath('/test/dateTime/text()', byTimestamp())
    +								xPath('/test/time/text()', byTime())
    +								xPath('/test/*/complex/text()', byEquality())
    +								xPath('/test/duck/@type', byEquality())
    +							}
    +						}
    +					}

    And below is an example of a YAML contract with XML request and response bodies:

    include::{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml

    Here is an example of an automatically generated test for XML response body:

    @Test
     public void validate_xmlMatches() throws Exception {
     	// given:
     	MockMvcRequestSpecification request = given()
    @@ -1908,7 +1948,7 @@ example:

    Groovy DSL.  messageFrom('input') // has the following body messageBody([ - bookName: 'foo' + bookName: 'foo' ]) // and the following headers messageHeaders { @@ -1918,7 +1958,7 @@ example:

    Groovy DSL.  outputMessage { sentTo('output') body([ - bookName: 'foo' + bookName: 'foo' ]) headers { header('BOOK-NAME', 'foo') @@ -1957,24 +1997,24 @@ generates a test that sends the input message to the defined destination. On the use those paradigms in messaging. In addition, Spring Cloud Contract Verifier also provides the consumer and producer methods, as presented in the following example (note that you can use either $ or value methods to provide consumer and producer -parts):

    Contract.make {
    -	label 'some_label'
    -	input {
    -		messageFrom value(consumer('jms:output'), producer('jms:input'))
    -		messageBody([
    -				bookName: 'foo'
    -		])
    -		messageHeaders {
    -			header('sample', 'header')
    -		}
    -	}
    -	outputMessage {
    -		sentTo $(consumer('jms:input'), producer('jms:output'))
    -		body([
    -				bookName: 'foo'
    -		])
    -	}
    -}

    8.11.4 Common

    In the input or outputMessage section you can call assertThat with the name +parts):

    					Contract.make {
    +						label 'some_label'
    +						input {
    +							messageFrom value(consumer('jms:output'), producer('jms:input'))
    +							messageBody([
    +									bookName: 'foo'
    +							])
    +							messageHeaders {
    +								header('sample', 'header')
    +							}
    +						}
    +						outputMessage {
    +							sentTo $(consumer('jms:input'), producer('jms:output'))
    +							body([
    +									bookName: 'foo'
    +							])
    +						}
    +					}

    8.11.4 Common

    In the input or outputMessage section you can call assertThat with the name of a method (e.g. assertThatMessageIsOnTheQueue()) that you have defined in the base class or in a static import. Spring Cloud Contract will execute that method in the generated test.

    8.12 Multiple Contracts in One File

    You can define multiple contracts in one file. Such a contract might resemble the @@ -1982,25 +2022,25 @@ following example:

    Groovy DSL. 

    import org.springframework.cloud.contract.spec.Contract
     
     [
    -        Contract.make {
    -            name("should post a user")
    -            request {
    -                method 'POST'
    -                url('/users/1')
    -            }
    -            response {
    -                status OK()
    -            }
    -        },
    -        Contract.make {
    -            request {
    -                method 'POST'
    -                url('/users/2')
    -            }
    -            response {
    -                status OK()
    -            }
    -        }
    +	Contract.make {
    +		name("should post a user")
    +		request {
    +			method 'POST'
    +			url('/users/1')
    +		}
    +		response {
    +			status OK()
    +		}
    +	},
    +	Contract.make {
    +		request {
    +			method 'POST'
    +			url('/users/2')
    +		}
    +		response {
    +			status OK()
    +		}
    +	}
     ]

    YAML. 

    ---
    @@ -2090,7 +2130,6 @@ testCompile 'org
     

    Next you need to make some changes to your base class like the following example.

    package com.example.fraud;
     
     import io.restassured.module.mockmvc.RestAssuredMockMvc;
    -
     import org.junit.Before;
     import org.junit.Rule;
     import org.junit.rules.TestName;
    @@ -2115,29 +2154,32 @@ testCompile 'org
     	@Rule
     	public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(OUTPUT);
     
    -	@Rule public TestName testName = new TestName();
    +	@Rule
    +	public TestName testName = new TestName();
     
     	@Autowired
     	private WebApplicationContext context;
     
     	@Before
     	public void setup() {
    -	RestAssuredMockMvc.mockMvc(MockMvcBuilders.webAppContextSetup(this.context)
    -			.apply(documentationConfiguration(this.restDocumentation))
    -			.alwaysDo(document(getClass().getSimpleName() + "_" + testName.getMethodName()))
    -			.build());
    +		RestAssuredMockMvc.mockMvc(MockMvcBuilders.webAppContextSetup(this.context)
    +				.apply(documentationConfiguration(this.restDocumentation))
    +				.alwaysDo(document(
    +						getClass().getSimpleName() + "_" + testName.getMethodName()))
    +				.build());
     	}
     
     	protected void assertThatRejectionReasonIsNull(Object rejectionReason) {
     		assert rejectionReason == null;
     	}
    -}
    -// end::base_class[]

    In case you are using the standalone setup, you can set up RestAssuredMockMvc like this:

    package com.example.fraud;
    +
    +}

    In case you are using the standalone setup, you can set up RestAssuredMockMvc like this:

    package com.example.fraud;
     
     import io.restassured.module.mockmvc.RestAssuredMockMvc;
     import org.junit.Before;
     import org.junit.Rule;
     import org.junit.rules.TestName;
    +
     import org.springframework.restdocs.JUnitRestDocumentation;
     import org.springframework.test.web.servlet.setup.MockMvcBuilders;
     
    @@ -2151,14 +2193,16 @@ testCompile 'org
     	@Rule
     	public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(OUTPUT);
     
    -	@Rule public TestName testName = new TestName();
    +	@Rule
    +	public TestName testName = new TestName();
     
     	@Before
     	public void setup() {
    -		RestAssuredMockMvc.standaloneSetup(MockMvcBuilders.standaloneSetup(new FraudDetectionController())
    +		RestAssuredMockMvc.standaloneSetup(MockMvcBuilders
    +				.standaloneSetup(new FraudDetectionController())
     				.apply(documentationConfiguration(this.restDocumentation))
    -				.alwaysDo(document(getClass().getSimpleName() + "_" + testName.getMethodName())));
    +				.alwaysDo(document(
    +						getClass().getSimpleName() + "_" + testName.getMethodName())));
     	}
     
    -}
    -// end::base_class[]
    [Tip]Tip

    You don’t need to specify the output directory for the generated snippets since version 1.2.0.RELEASE of Spring REST Docs.

    \ No newline at end of file +}
    [Tip]Tip

    You don’t need to specify the output directory for the generated snippets since version 1.2.0.RELEASE of Spring REST Docs.

    \ No newline at end of file diff --git a/multi/multi_stub-runner-for-messaging.html b/multi/multi_stub-runner-for-messaging.html index 04f7e48b76..7f3afc58db 100644 --- a/multi/multi_stub-runner-for-messaging.html +++ b/multi/multi_stub-runner-for-messaging.html @@ -9,6 +9,11 @@ That way the only remaining framework is Spring AMQP.

    import java.util.Collection; import java.util.Map; +/** + * Contract for triggering stub messages. + * + * @author Marcin Grzejszczak + */ public interface StubTrigger { /** @@ -16,6 +21,8 @@ That way the only remaining framework is Spring AMQP.

    boolean trigger(String ivyNotation, String labelName); @@ -24,6 +31,7 @@ That way the only remaining framework is Spring AMQP.

    boolean trigger(String labelName); @@ -37,9 +45,8 @@ That way the only remaining framework is Spring AMQP.

    boolean trigger(); /** - * Returns a mapping of ivy notation of a dependency to all the labels it has. - * * Feature related to messaging. + * @return a mapping of ivy notation of a dependency to all the labels it has. */ Map<String, Collection<String>> labels(); @@ -100,9 +107,11 @@ Remember to annotate your test class with @AutoConfigureSt } }

    Scenario 1 (no input message)

    So as to trigger a message via the return_book_1 label we’ll use the StubTigger interface as follows

    stubFinder.trigger('return_book_1')

    Next we’ll want to listen to the output of the message sent to jms:output

    Exchange receivedMessage = consumerTemplate.receive('jms:output', 5000)

    And the received message would pass the following assertions

    receivedMessage != null
     assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
    -receivedMessage.in.headers.get('BOOK-NAME') == 'foo'

    Scenario 2 (output triggered by input)

    Since the route is set for you it’s enough to just send a message to the jms:output destination.

    producerTemplate.sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header'])

    Next we’ll want to listen to the output of the message sent to jms:output

    Exchange receivedMessage = consumerTemplate.receive('jms:output', 5000)

    And the received message would pass the following assertions

    receivedMessage != null
    +receivedMessage.in.headers.get('BOOK-NAME') == 'foo'

    Scenario 2 (output triggered by input)

    Since the route is set for you it’s enough to just send a message to the jms:output destination.

    producerTemplate.
    +		sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header'])

    Next we’ll want to listen to the output of the message sent to jms:output

    Exchange receivedMessage = consumerTemplate.receive('jms:output', 5000)

    And the received message would pass the following assertions

    receivedMessage != null
     assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
    -receivedMessage.in.headers.get('BOOK-NAME') == 'foo'

    Scenario 3 (input with no output)

    Since the route is set for you it’s enough to just send a message to the jms:output destination.

    producerTemplate.sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header'])

    7.3 Stub Runner Integration

    Spring Cloud Contract Verifier Stub Runner’s messaging module gives you an easy way to +receivedMessage.in.headers.get('BOOK-NAME') == 'foo'

    Scenario 3 (input with no output)

    Since the route is set for you it’s enough to just send a message to the jms:output destination.

    producerTemplate.
    +		sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header'])

    7.3 Stub Runner Integration

    Spring Cloud Contract Verifier Stub Runner’s messaging module gives you an easy way to integrate with Spring Integration. For the provided artifacts, it automatically downloads the stubs and registers the required routes.

    7.3.1 Adding the Runner to the Project

    You can have both Spring Integration and Spring Cloud Contract Stub Runner on the classpath. Remember to annotate your test class with @AutoConfigureStubRunner.

    7.3.2 Disabling the functionality

    If you need to disable this functionality, set the @@ -158,9 +167,9 @@ classpath. Remember to annotate your test class with @Auto } } }

    and the following Spring Integration Route:

    <?xml version="1.0" encoding="UTF-8"?>
    -<beans:beans xmlns="http://www.springframework.org/schema/integration"
    -			 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    +<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     			 xmlns:beans="http://www.springframework.org/schema/beans"
    +			 xmlns="http://www.springframework.org/schema/integration"
     			 xsi:schemaLocation="http://www.springframework.org/schema/beans
     			http://www.springframework.org/schema/beans/spring-beans.xsd
     			http://www.springframework.org/schema/integration
    @@ -293,29 +302,29 @@ to disable them explicitly by setting the  stubrunner.stre
     │   └── MANIFEST.MF
     └── contracts
         └── shouldProduceValidPersonData.groovy

    Consider the following contract:

    Contract.make {
    -    // Human readable description
    -    description 'Should produce valid person data'
    -    // Label by means of which the output message can be triggered
    -    label 'contract-test.person.created.event'
    -    // input to the contract
    -    input {
    -        // the contract will be triggered by a method
    -        triggeredBy('createPerson()')
    -    }
    -    // output message of the contract
    -    outputMessage {
    -        // destination to which the output message will be sent
    -        sentTo 'contract-test.exchange'
    -        headers {
    -            header('contentType': 'application/json')
    -            header('__TypeId__': 'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person')
    -        }
    -        // the body of the output message
    -        body ([
    -                id: $(consumer(9), producer(regex("[0-9]+"))),
    -                name: "me"
    -        ])
    -    }
    +	// Human readable description
    +	description 'Should produce valid person data'
    +	// Label by means of which the output message can be triggered
    +	label 'contract-test.person.created.event'
    +	// input to the contract
    +	input {
    +		// the contract will be triggered by a method
    +		triggeredBy('createPerson()')
    +	}
    +	// output message of the contract
    +	outputMessage {
    +		// destination to which the output message will be sent
    +		sentTo 'contract-test.exchange'
    +		headers {
    +			header('contentType': 'application/json')
    +			header('__TypeId__': 'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person')
    +		}
    +		// the body of the output message
    +		body([
    +				id  : $(consumer(9), producer(regex("[0-9]+"))),
    +				name: "me"
    +		])
    +	}
     }

    Now consider the following Spring configuration:

    stubrunner:
       repositoryRoot: classpath:m2repo/repository/
       ids: org.springframework.cloud.contract.verifier.stubs.amqp:spring-cloud-contract-amqp-test:0.4.0-SNAPSHOT:stubs
    @@ -340,7 +349,7 @@ definition is matched and invoked with the contract message.

    return container;
    -}

    Also, the following annotated listener matches and is invoked:

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "test.queue"), exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true")))
    +}

    Also, the following annotated listener matches and is invoked:

    @RabbitListener(bindings = @QueueBinding(value = @Queue("test.queue"), exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true")))
     public void handlePerson(Person person) {
     	this.person = person;
     }
    [Note]Note

    The message is directly handed over to the onMessage method of the diff --git a/single/spring-cloud-contract.html b/single/spring-cloud-contract.html index b54febb335..1bc169d79e 100644 --- a/single/spring-cloud-contract.html +++ b/single/spring-cloud-contract.html @@ -125,19 +125,19 @@ org.springframework.cloud.contract.spec.Contract.make { "rejection.reason": "Amount too high" headers: Content-Type: application/json;charset=UTF-8

    In the case of messaging, you can define:

    • The input and the output messages can be defined (taking into account from and where it -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:

    def contractDsl = Contract.make {
    -	label 'some_label'
    -	input {
    -		messageFrom('jms:delete')
    -		messageBody([
    -				bookName: 'foo'
    -		])
    -		messageHeaders {
    -			header('sample', 'header')
    -		}
    -		assertThat('bookWasDeleted()')
    -	}
    -}

    The following example shows the same contract expressed in YAML:

    label: some_label
    +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:

    			def contractDsl = Contract.make {
    +				label 'some_label'
    +				input {
    +					messageFrom('jms:delete')
    +					messageBody([
    +							bookName: 'foo'
    +					])
    +					messageHeaders {
    +						header('sample', 'header')
    +					}
    +					assertThat('bookWasDeleted()')
    +				}
    +			}

    The following example shows the same contract expressed in YAML:

    label: some_label
     input:
       messageFrom: jms:delete
       messageBody:
    @@ -267,7 +267,23 @@ to the following in the build logs:

    package contracts
    +

    /*
    + * Copyright 2013-2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package contracts
     
     org.springframework.cloud.contract.spec.Contract.make {
     	request { // (1)
    @@ -275,7 +291,7 @@ org.springframework.cloud.contract.spec.Contract.make {
     		url '/fraudcheck' // (3)
     		body([ // (4)
     			   "client.id": $(regex('[0-9]{10}')),
    -			   loanAmount: 99999
    +			   loanAmount : 99999
     		])
     		headers { // (5)
     			contentType('application/json')
    @@ -284,7 +300,7 @@ org.springframework.cloud.contract.spec.Contract.make {
     	response { // (6)
     		status OK() // (7)
     		body([ // (8)
    -			   fraudCheckStatus: "FRAUD",
    +			   fraudCheckStatus  : "FRAUD",
     			   "rejection.reason": "Amount too high"
     		])
     		headers { // (9)
    @@ -379,13 +395,12 @@ response: # (7)
     #(10) - with header `Content-Type` equal to `application/json;charset=UTF-8`

    2.4.4 Client Side

    Spring Cloud Contract generates stubs, which you can use during client-side testing. You get a running WireMock instance/Messaging route that simulates the service. -You would like to feed that instance with a proper stub definition.

    At some point in time, you need to send a request to the Fraud Detection service.

    ResponseEntity<FraudServiceResponse> response =
    -		restTemplate.exchange("http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
    -				new HttpEntity<>(request, httpHeaders),
    -				FraudServiceResponse.class);

    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.

    @RunWith(SpringRunner.class)
    +You would like to feed that instance with a proper stub definition.

    At some point in time, you need to send a request to the Fraud Detection service.

    ResponseEntity<FraudServiceResponse> response = restTemplate.exchange(
    +		"http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
    +		new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class);

    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.

    @RunWith(SpringRunner.class)
     @SpringBootTest(webEnvironment = WebEnvironment.NONE)
    -@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
    -		stubsMode = StubRunnerProperties.StubsMode.LOCAL)
    +@AutoConfigureStubRunner(ids = {
    +		"com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
     public class LoanApplicationServiceTests {

    After that, during the tests, Spring Cloud Contract automatically finds the stubs (simulating the real service) in the Maven repository and exposes them on a configured (or random) port.

    2.4.5 Server Side

    Since you are developing your stub, you need to be sure that it actually resembles your @@ -494,16 +509,31 @@ following section to your build:

    Maven.  }

    Assume that you have written a test of your new feature. If a loan application for a big amount is received, the system should reject that loan application with some description.

    Write the missing implementation.

    At some point in time, you need to send a request to the Fraud Detection service. Assume that you need to send the request containing the ID of the client and the amount the -client wants to borrow. You want to send it to the /fraudcheck url via the PUT method.

    ResponseEntity<FraudServiceResponse> response =
    -		restTemplate.exchange("http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
    -				new HttpEntity<>(request, httpHeaders),
    -				FraudServiceResponse.class);

    For simplicity, the port of the Fraud Detection service is set to 8080, and the +client wants to borrow. You want to send it to the /fraudcheck url via the PUT method.

    ResponseEntity<FraudServiceResponse> response = restTemplate.exchange(
    +		"http://localhost:" + port + "/fraudcheck", HttpMethod.PUT,
    +		new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class);

    For simplicity, the port of the Fraud Detection service is set to 8080, and the application runs on 8090.

    If you start the test at this point, it breaks, because no service currently runs on port 8080.

    Clone the Fraud Detection service repository locally.

    You can start by playing around with the server side contract. To do so, you must first clone it.

    $ git clone https://your-git-server.com/server-side.git local-http-server-repo

    Define the contract locally in the repo of Fraud Detection service.

    As a consumer, you need to define what exactly you want to achieve. You need to formulate your expectations. To do so, write the following contract:

    [Important]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.  -

    package contracts
    +

    /*
    + * Copyright 2013-2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package contracts
     
     org.springframework.cloud.contract.spec.Contract.make {
     	request { // (1)
    @@ -511,7 +541,7 @@ org.springframework.cloud.contract.spec.Contract.make {
     		url '/fraudcheck' // (3)
     		body([ // (4)
     			   "client.id": $(regex('[0-9]{10}')),
    -			   loanAmount: 99999
    +			   loanAmount : 99999
     		])
     		headers { // (5)
     			contentType('application/json')
    @@ -520,7 +550,7 @@ org.springframework.cloud.contract.spec.Contract.make {
     	response { // (6)
     		status OK() // (7)
     		body([ // (8)
    -			   fraudCheckStatus: "FRAUD",
    +			   fraudCheckStatus  : "FRAUD",
     			   "rejection.reason": "Amount too high"
     		])
     		headers { // (9)
    @@ -681,8 +711,8 @@ Application service):

    Add the Spring Cloud Co collaborators. (Optional step) Because you’re playing with the collaborators offline, you can also provide the offline work switch (StubRunnerProperties.StubsMode.LOCAL).

    @RunWith(SpringRunner.class)
     @SpringBootTest(webEnvironment = WebEnvironment.NONE)
    -@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
    -		stubsMode = StubRunnerProperties.StubsMode.LOCAL)
    +@AutoConfigureStubRunner(ids = {
    +		"com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL)
     public class LoanApplicationServiceTests {

    Now, when you run your tests, you see something like this:

    2016-07-19 14:22:25.403  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is + - will try to resolve the latest version
     2016-07-19 14:22:25.438  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is 0.0.1-SNAPSHOT
     2016-07-19 14:22:25.439  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact com.example:http-server:jar:stubs:0.0.1-SNAPSHOT using remote repositories []
    @@ -718,12 +748,29 @@ make the name of the base test class. In our case, the contracts were placed und
     the contracts folder, pick only one, which should be fraud. Add the Base suffix and
     capitalize fraud. That gives you the FraudBase test class name.

    All the generated tests extend that class. Over there, you can set up your Spring Context or whatever is necessary. In this case, use Rest Assured MVC to -start the server side FraudDetectionController.

    package com.example.fraud;
    +start the server side FraudDetectionController.

    /*
    + * Copyright 2013-2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +package com.example.fraud;
     
     import io.restassured.module.mockmvc.RestAssuredMockMvc;
     import org.junit.Before;
     
     public class FraudBase {
    +
     	@Before
     	public void setup() {
     		RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(),
    @@ -745,6 +792,7 @@ start the server side FraudDetectionController.

    public void assertThatRejectionReasonIsNull(Object rejectionReason) { assert rejectionReason == null; } + }

    Now, if you run the ./mvnw clean install, you get something like this:

    Results :
     
     Tests in error:
    @@ -898,8 +946,9 @@ consumer you will break with your local changes.

    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 repo.

    Example of a pom.xml inside the server folder.

    <?xml version="1.0" encoding="UTF-8"?>
    -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    -	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    +		 xmlns="http://maven.apache.org/POM/4.0.0"
    +		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     	<modelVersion>4.0.0</modelVersion>
     
     	<groupId>com.example</groupId>
    @@ -913,14 +962,16 @@ one to one to the contents of the repo.

    Example of a <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> - <relativePath /> + <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> - <spring-cloud-contract.version>2.1.1.BUILD-SNAPSHOT</spring-cloud-contract.version> - <spring-cloud-release.version>Greenwich.BUILD-SNAPSHOT</spring-cloud-release.version> + <spring-cloud-contract.version>2.1.1.BUILD-SNAPSHOT + </spring-cloud-contract.version> + <spring-cloud-release.version>Greenwich.BUILD-SNAPSHOT + </spring-cloud-release.version> <excludeBuildFolders>true</excludeBuildFolders> </properties> @@ -1007,7 +1058,8 @@ one to one to the contents of the repo.

    Example of a </project>

    As you can see there are no dependencies other than the Spring Cloud Contract Maven Plugin. Those poms are necessary for the consumer side to run mvn clean install -DskipTests to locally install stubs of the producer project.

    The pom.xml in the root folder can look like this:

    <?xml version="1.0" encoding="UTF-8"?>
    -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    +		 xmlns="http://maven.apache.org/POM/4.0.0"
     		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     	<modelVersion>4.0.0</modelVersion>
     
    @@ -1016,7 +1068,9 @@ Those poms are necessary for the consumer side to run mvn
     	<version>0.0.1-SNAPSHOT</version>
     
     	<name>Contracts</name>
    -	<description>Contains all the Spring Cloud Contracts, well, contracts. JAR used by the producers to generate tests and stubs</description>
    +	<description>Contains all the Spring Cloud Contracts, well, contracts. JAR used by the
    +		producers to generate tests and stubs
    +	</description>
     
     	<properties>
     		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    @@ -1046,8 +1100,8 @@ Those poms are necessary for the consumer side to run mvn
     		</plugins>
     	</build>
     
    -</project>

    It’s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
    -		  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    +</project>

    It’s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here:

    <assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    +		  xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
     		  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
     	<id>project</id>
     	<formats>
    @@ -1078,7 +1132,9 @@ of the JAR containing the contracts:

    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
     	<configuration>
     		<contractsMode>REMOTE</contractsMode>
    -		<contractsRepositoryUrl>http://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl>
    +		<contractsRepositoryUrl>
    +			http://link/to/your/nexus/or/artifactory/or/sth
    +		</contractsRepositoryUrl>
     		<contractDependency>
     			<groupId>com.example.standalone</groupId>
     			<artifactId>contracts</artifactId>
    @@ -1664,7 +1720,7 @@ name of the base class for the matched contract. You have to provide a list call
     contractPackageRegex to baseClassFQN mapping. Consider the following example:

    baseClassForTests = "com.example.FooBase"
     baseClassMappings {
     	baseClassMapping('.*/com/.*', 'com.example.ComBase')
    -	baseClassMapping('.*/bar/.*':'com.example.BarBase')
    +	baseClassMapping('.*/bar/.*': 'com.example.BarBase')
     }

    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. @@ -2215,20 +2271,20 @@ meanings for different messaging implementations. For destination of a channel. Then, if there is no such destination it is resolved as a channel name. For Camel, that’s a certain component (for example, jms).

    5.3.1 Scenario 1: No Input Message

    For the given contract:

    Groovy DSL.  -

    def contractDsl = Contract.make {
    -	label 'some_label'
    -	input {
    -		triggeredBy('bookReturnedTriggered()')
    -	}
    -	outputMessage {
    -		sentTo('activemq:output')
    -		body('''{ "bookName" : "foo" }''')
    -		headers {
    -			header('BOOK-NAME', 'foo')
    -			messagingContentType(applicationJson())
    -		}
    -	}
    -}

    +

    			def contractDsl = Contract.make {
    +				label 'some_label'
    +				input {
    +					triggeredBy('bookReturnedTriggered()')
    +				}
    +				outputMessage {
    +					sentTo('activemq:output')
    +					body('''{ "bookName" : "foo" }''')
    +					headers {
    +						header('BOOK-NAME', 'foo')
    +						messagingContentType(applicationJson())
    +					}
    +				}
    +			}

    YAML. 

    label: some_label
     input:
    @@ -2240,7 +2296,7 @@ outputMessage:
       headers:
         BOOK-NAME: foo
         contentType: application/json

    -

    The following JUnit test is created:

    '''
    +

    The following JUnit test is created:

    					'''
      // when:
       bookReturnedTriggered();
     
    @@ -2254,7 +2310,7 @@ outputMessage:
      // and:
       DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
       assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
    -'''

    And the following Spock test would be created:

    '''
    +'''

    And the following Spock test would be created:

    					'''
      when:
       bookReturnedTriggered()
     
    @@ -2268,27 +2324,27 @@ outputMessage:
       assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
     
     '''

    5.3.2 Scenario 2: Output Triggered by Input

    For the given contract:

    Groovy DSL.  -

    def contractDsl = Contract.make {
    -	label 'some_label'
    -	input {
    -		messageFrom('jms:input')
    -		messageBody([
    -				bookName: 'foo'
    -		])
    -		messageHeaders {
    -			header('sample', 'header')
    -		}
    -	}
    -	outputMessage {
    -		sentTo('jms:output')
    -		body([
    -				bookName: 'foo'
    -		])
    -		headers {
    -			header('BOOK-NAME', 'foo')
    -		}
    -	}
    -}

    +

    			def contractDsl = Contract.make {
    +				label 'some_label'
    +				input {
    +					messageFrom('jms:input')
    +					messageBody([
    +							bookName: 'foo'
    +					])
    +					messageHeaders {
    +						header('sample', 'header')
    +					}
    +				}
    +				outputMessage {
    +					sentTo('jms:output')
    +					body([
    +							bookName: 'foo'
    +					])
    +					headers {
    +						header('BOOK-NAME', 'foo')
    +					}
    +				}
    +			}

    YAML. 

    label: some_label
     input:
    @@ -2303,7 +2359,7 @@ outputMessage:
         bookName: foo
       headers:
         BOOK-NAME: foo

    -

    The following JUnit test is created:

    '''
    +

    The following JUnit test is created:

    					'''
     // given:
      ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
       "{\\"bookName\\":\\"foo\\"}"
    @@ -2321,7 +2377,7 @@ outputMessage:
     // and:
      DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));
      assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
    -'''

    And the following Spock test would be created:

    """\
    +'''

    And the following Spock test would be created:

    					"""\
     given:
        ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
         '''{"bookName":"foo"}''',
    @@ -2339,19 +2395,19 @@ and:
        DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload))
        assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
     """

    5.3.3 Scenario 3: No Output Message

    For the given contract:

    Groovy DSL.  -

    def contractDsl = Contract.make {
    -	label 'some_label'
    -	input {
    -		messageFrom('jms:delete')
    -		messageBody([
    -				bookName: 'foo'
    -		])
    -		messageHeaders {
    -			header('sample', 'header')
    -		}
    -		assertThat('bookWasDeleted()')
    -	}
    -}

    +

    			def contractDsl = Contract.make {
    +				label 'some_label'
    +				input {
    +					messageFrom('jms:delete')
    +					messageBody([
    +							bookName: 'foo'
    +					])
    +					messageHeaders {
    +						header('sample', 'header')
    +					}
    +					assertThat('bookWasDeleted()')
    +				}
    +			}

    YAML. 

    label: some_label
     input:
    @@ -2361,7 +2417,7 @@ input:
       messageHeaders:
         sample: header
       assertThat: bookWasDeleted()

    -

    The following JUnit test is created:

    '''
    +

    The following JUnit test is created:

    					'''
     // given:
      ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
     	"{\\"bookName\\":\\"foo\\"}"
    @@ -2373,7 +2429,7 @@ input:
     
     // then:
      bookWasDeleted();
    -'''

    And the following Spock test would be created:

    '''
    +'''

    And the following Spock test would be created:

    					'''
     given:
     	 ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
     		\'\'\'{"bookName":"foo"}\'\'\',
    @@ -2682,7 +2738,7 @@ case might be starting WireMock for the given artifact id, on an HTTPs port. Exa
     	}
     }

    You can then reuse it via the annotation

    @AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/",
    -			httpServerStubConfigurer = HttpsForFraudDetection)

    Whenever an https port is found, it will take precedence over the http one.

    6.3.2 Running stubs

    Running using main app

    You can set the following options to the main class:

    -c, --classifier                Suffix for the jar containing stubs (e.
    +		httpServerStubConfigurer = HttpsForFraudDetection)

    Whenever an https port is found, it will take precedence over the http one.

    6.3.2 Running stubs

    Running using main app

    You can set the following options to the main class:

    -c, --classifier                Suffix for the jar containing stubs (e.
                                       g. 'stubs' if the stub jar would
                                       have a 'stubs' classifier for stubs:
                                       foobar-stubs ). Defaults to 'stubs'
    @@ -2745,11 +2801,20 @@ mappings available for the given server:

    ["uuid" : "f9152eb9-bf77-4c38-8289-90be7d10d0d7"
     },
     ...
    -]

    Messaging Stubs

    Depending on the provided Stub Runner dependency and the DSL the messaging routes are automatically set up.

    6.4 Stub Runner JUnit Rule and Stub Runner JUnit5 Extension

    Stub Runner comes with a JUnit rule thanks to which you can very easily download and run stubs for given group and artifact id:

    @ClassRule public static StubRunnerRule rule = new StubRunnerRule()
    -		.repoRoot(repoRoot())
    +]

    Messaging Stubs

    Depending on the provided Stub Runner dependency and the DSL the messaging routes are automatically set up.

    6.4 Stub Runner JUnit Rule and Stub Runner JUnit5 Extension

    Stub Runner comes with a JUnit rule thanks to which you can very easily download and run stubs for given group and artifact id:

    @ClassRule
    +public static StubRunnerRule rule = new StubRunnerRule().repoRoot(repoRoot())
     		.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
    -		.downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")
    -		.downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer");

    There’s also a StubRunnerExtension available for JUnit 5. StubRunnerRule and StubRunnerExtension work in a very + .downloadStub("org.springframework.cloud.contract.verifier.stubs", + "loanIssuance") + .downloadStub( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"); + +@BeforeClass +@AfterClass +public static void setupProps() { + System.clearProperty("stubrunner.repository.root"); + System.clearProperty("stubrunner.classifier"); +}

    There’s also a StubRunnerExtension available for JUnit 5. StubRunnerRule and StubRunnerExtension work in a very similar fashion. After the rule/ extension is executed, Stub Runner connects to your Maven repository and for the given list of dependencies tries to:

    • download them
    • cache them locally
    • unzip them to a temporary folder
    • start a WireMock server for each Maven dependency on a random port from the provided range of ports / provided port
    • feed the WireMock server with all JSON files that are valid WireMock definitions
    • can also send messages (remember to pass an implementation of MessageVerifier interface)

    Stub Runner uses Eclipse Aether mechanism to download the Maven dependencies. Check their docs for more information.

    Since the StubRunnerRule and StubRunnerExtension implement the StubFinder they allow you to find the started stubs:

    package org.springframework.cloud.contract.stubrunner;
     
    @@ -2759,6 +2824,11 @@ Check their import org.springframework.cloud.contract.spec.Contract;
     
    +/**
    + * Contract for finding registered stubs.
    + *
    + * @author Marcin Grzejszczak
    + */
     public interface StubFinder extends StubTrigger {
     
     	/**
    @@ -2766,7 +2836,9 @@ Check their 
     	URL findStubUrl(String groupId, String artifactId) throws StubNotFoundException;
     
    @@ -2776,20 +2848,23 @@ Check their 
     	URL findStubUrl(String ivyNotation) throws StubNotFoundException;
     
     	/**
    -	 * Returns all running stubs
    +	 * @return all running stubs
     	 */
     	RunningStubs findAllRunningStubs();
     
     	/**
    -	 * Returns the list of Contracts
    +	 * @return the list of Contracts
     	 */
     	Map<StubConfiguration, Collection<Contract>> getContracts();
     
    -}

    Example of usage in Spock tests:

    @ClassRule @Shared StubRunnerRule rule = new StubRunnerRule()
    +}

    Example of usage in Spock tests:

    @ClassRule
    +@Shared
    +StubRunnerRule rule = new StubRunnerRule()
     		.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
     		.repoRoot(StubRunnerRuleSpec.getResource("/m2repo/repository").toURI().toString())
     		.downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")
    @@ -2817,64 +2892,104 @@ def 'should outp
     		def url = rule.findStubUrl('fraudDetectionServer')
     	then:
     		new File("target/outputmappingsforrule", "fraudDetectionServer_${url.port}").exists()
    -}

    Example of usage in JUnit tests:

    @Test
    -public void should_start_wiremock_servers() throws Exception {
    -	// expect: 'WireMocks are running'
    -		then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")).isNotNull();
    +}

    Example of usage in JUnit tests:

    	@Test
    +	public void should_start_wiremock_servers() throws Exception {
    +		// expect: 'WireMocks are running'
    +		then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs",
    +				"loanIssuance")).isNotNull();
     		then(rule.findStubUrl("loanIssuance")).isNotNull();
    -		then(rule.findStubUrl("loanIssuance")).isEqualTo(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance"));
    -		then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isNotNull();
    -	// and:
    +		then(rule.findStubUrl("loanIssuance")).isEqualTo(rule.findStubUrl(
    +				"org.springframework.cloud.contract.verifier.stubs", "loanIssuance"));
    +		then(rule.findStubUrl(
    +				"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"))
    +						.isNotNull();
    +		// and:
     		then(rule.findAllRunningStubs().isPresent("loanIssuance")).isTrue();
    -		then(rule.findAllRunningStubs().isPresent("org.springframework.cloud.contract.verifier.stubs", "fraudDetectionServer")).isTrue();
    -		then(rule.findAllRunningStubs().isPresent("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isTrue();
    -	// and: 'Stubs were registered'
    -		then(httpGet(rule.findStubUrl("loanIssuance").toString() + "/name")).isEqualTo("loanIssuance");
    -		then(httpGet(rule.findStubUrl("fraudDetectionServer").toString() + "/name")).isEqualTo("fraudDetectionServer");
    +		then(rule.findAllRunningStubs().isPresent(
    +				"org.springframework.cloud.contract.verifier.stubs",
    +				"fraudDetectionServer")).isTrue();
    +		then(rule.findAllRunningStubs().isPresent(
    +				"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"))
    +						.isTrue();
    +		// and: 'Stubs were registered'
    +		then(httpGet(rule.findStubUrl("loanIssuance").toString() + "/name"))
    +				.isEqualTo("loanIssuance");
    +		then(httpGet(rule.findStubUrl("fraudDetectionServer").toString() + "/name"))
    +				.isEqualTo("fraudDetectionServer");
    +	}
    +
    +	private String httpGet(String url) throws Exception {
    +		try (InputStream stream = URI.create(url).toURL().openStream()) {
    +			return StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
    +		}
    +	}
    +
     }

    JUnit 5 Extension example:

    // Visible for Junit
     @RegisterExtension
     static StubRunnerExtension stubRunnerExtension = new StubRunnerExtension()
    -        .repoRoot(repoRoot())
    -        .stubsMode(StubRunnerProperties.StubsMode.REMOTE)
    -        .downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")
    -        .downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")
    -        .withMappingsOutputFolder("target/outputmappingsforrule");
    +		.repoRoot(repoRoot()).stubsMode(StubRunnerProperties.StubsMode.REMOTE)
    +		.downloadStub("org.springframework.cloud.contract.verifier.stubs",
    +				"loanIssuance")
    +		.downloadStub(
    +				"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")
    +		.withMappingsOutputFolder("target/outputmappingsforrule");
     
    -@Test
    -void should_start_WireMock_servers() {
    -    assertThat(stubRunnerExtension.findStubUrl("org.springframework.cloud.contract.verifier.stubs",
    -            "loanIssuance")).isNotNull();
    -    assertThat(stubRunnerExtension.findStubUrl("loanIssuance")).isNotNull();
    -    assertThat(stubRunnerExtension.findStubUrl("loanIssuance")).isEqualTo(stubRunnerExtension
    -            .findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance"));
    -    assertThat(stubRunnerExtension
    -            .findStubUrl("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isNotNull();
    +@BeforeAll
    +@AfterAll
    +static void setupProps() {
    +	System.clearProperty("stubrunner.repository.root");
    +	System.clearProperty("stubrunner.classifier");
    +}
    +
    +private static String repoRoot() {
    +	try {
    +		return StubRunnerRuleJUnitTest.class.getResource("/m2repo/repository/")
    +				.toURI().toString();
    +	}
    +	catch (Exception e) {
    +		return "";
    +	}
     }

    Check the Common properties for JUnit and Spring for more information on how to apply global configuration of Stub Runner.

    [Important]Important

    To use the JUnit rule or JUnit 5 extension together with messaging, you have to provide an implementation of the MessageVerifier interface to the rule builder (e.g. rule.messageVerifier(new MyMessageVerifier())). If you don’t do this, then whenever you try to send a message an exception will be thrown.

    6.4.1 Maven settings

    The stub downloader honors Maven settings for a different local repository folder. Authentication details for repositories and profiles are currently not taken into account, so you need to specify it using the properties mentioned above.

    6.4.2 Providing fixed ports

    You can also run your stubs on fixed ports. You can do it in two different ways. One is to pass it in the properties, and the other via fluent API of -JUnit rule.

    6.4.3 Fluent API

    When using the StubRunnerRule or StubRunnerExtension you can add a stub to download and then pass the port for the last downloaded stub.

    @ClassRule public static StubRunnerRule rule = new StubRunnerRule()
    -		.repoRoot(repoRoot())
    +JUnit rule.

    6.4.3 Fluent API

    When using the StubRunnerRule or StubRunnerExtension you can add a stub to download and then pass the port for the last downloaded stub.

    @ClassRule
    +public static StubRunnerRule rule = new StubRunnerRule().repoRoot(repoRoot())
     		.stubsMode(StubRunnerProperties.StubsMode.REMOTE)
    -		.downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")
    -		.withPort(12345)
    -		.downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:12346");

    You can see that for this example the following test is valid:

    then(rule.findStubUrl("loanIssuance")).isEqualTo(URI.create("http://localhost:12345").toURL());
    -then(rule.findStubUrl("fraudDetectionServer")).isEqualTo(URI.create("http://localhost:12346").toURL());

    6.4.4 Stub Runner with Spring

    Sets up Spring configuration of the Stub Runner project.

    By providing a list of stubs inside your configuration file the Stub Runner automatically downloads + .downloadStub("org.springframework.cloud.contract.verifier.stubs", + "loanIssuance") + .withPort(12345).downloadStub( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:12346"); + +@BeforeClass +@AfterClass +public static void setupProps() { + System.clearProperty("stubrunner.repository.root"); + System.clearProperty("stubrunner.classifier"); +}

    You can see that for this example the following test is valid:

    then(rule.findStubUrl("loanIssuance"))
    +		.isEqualTo(URI.create("http://localhost:12345").toURL());
    +then(rule.findStubUrl("fraudDetectionServer"))
    +		.isEqualTo(URI.create("http://localhost:12346").toURL());

    6.4.4 Stub Runner with Spring

    Sets up Spring configuration of the Stub Runner project.

    By providing a list of stubs inside your configuration file the Stub Runner automatically downloads and registers in WireMock the selected stubs.

    If you want to find the URL of your stubbed dependency you can autowire the StubFinder interface and use its methods as presented below:

    @ContextConfiguration(classes = Config, loader = SpringBootContextLoader)
     @SpringBootTest(properties = [" stubrunner.cloud.enabled=false",
     		'foo=${stubrunner.runningstubs.fraudDetectionServer.port}',
     		'fooWithGroup=${stubrunner.runningstubs.org.springframework.cloud.contract.verifier.stubs.fraudDetectionServer.port}'])
     @AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/",
    -			httpServerStubConfigurer = HttpsForFraudDetection)
    +		httpServerStubConfigurer = HttpsForFraudDetection)
     @ActiveProfiles("test")
     class StubRunnerConfigurationSpec extends Specification {
     
    -	@Autowired StubFinder stubFinder
    -	@Autowired Environment environment
    -	@StubRunnerPort("fraudDetectionServer") int fraudDetectionServerPort
    -	@StubRunnerPort("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer") int fraudDetectionServerPortWithGroupId
    -	@Value('${foo}') Integer foo
    +	@Autowired
    +	StubFinder stubFinder
    +	@Autowired
    +	Environment environment
    +	@StubRunnerPort("fraudDetectionServer")
    +	int fraudDetectionServerPort
    +	@StubRunnerPort("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")
    +	int fraudDetectionServerPortWithGroupId
    +	@Value('${foo}')
    +	Integer foo
     
     	@BeforeClass
     	@AfterClass
    @@ -2972,8 +3087,7 @@ its methods as presented below:

    return httpStubConfiguration
     		}
     	}
    -}
    -// end::test[]

    for the following configuration file:

    stubrunner:
    +}

    for the following configuration file:

    stubrunner:
       repositoryRoot: classpath:m2repo/repository/
       ids:
         - org.springframework.cloud.contract.verifier.stubs:loanIssuance
    @@ -2982,8 +3096,8 @@ its methods as presented below:

    @AutoConfigureStubRunner.
     Below you can find an example of achieving the same result by setting values on the annotation.

    @AutoConfigureStubRunner(
     		ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance",
    -		"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer",
    -		"org.springframework.cloud.contract.verifier.stubs:bootService"],
    +				"org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer",
    +				"org.springframework.cloud.contract.verifier.stubs:bootService"],
     		stubsMode = StubRunnerProperties.StubsMode.REMOTE,
     		repositoryRoot = "classpath:m2repo/repository/")

    Stub Runner Spring registers environment variables in the following manner for every registered WireMock server. Example for Stub Runner ids @@ -3004,8 +3118,7 @@ or DiscoveryClient directly, to call those stubbed }

    for the following configuration file

    stubrunner:
       idsToServiceIds:
         ivyNotation: someValueInsideYourCode
    -    fraudDetectionServer: someNameThatShouldMapFraudDetectionServer
    -# end::ids[]

    Test profiles and service discovery

    In your integration tests you typically don’t want to call neither a discovery service (e.g. Eureka) + fraudDetectionServer: someNameThatShouldMapFraudDetectionServer

    Test profiles and service discovery

    In your integration tests you typically don’t want to call neither a discovery service (e.g. Eureka) or Config Server. That’s why you create an additional test configuration in which you want to disable these features.

    Due to certain limitations of spring-cloud-commons to achieve this you have disable these properties via a static block like presented below (example for Eureka)

        //Hack to work around https://github.com/spring-cloud/spring-cloud-commons/issues/156
    @@ -3036,7 +3149,8 @@ the Stub Runner server. It will be available at port 8750<
     @ActiveProfiles("test")
     class StubRunnerBootSpec extends Specification {
     
    -	@Autowired StubRunning stubRunning
    +	@Autowired
    +	StubRunning stubRunning
     
     	def setup() {
     		RestAssuredMockMvc.standaloneSetup(new HttpStubsController(stubRunning),
    @@ -3077,7 +3191,7 @@ the Stub Runner server. It will be available at port 8750<
     			String response = RestAssuredMockMvc.get('/triggers').body.asString()
     		then:
     			def root = new JsonSlurper().parseText(response)
    -			root.'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'?.containsAll(["delete_book","return_book_1","return_book_2"])
    +			root.'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'?.containsAll(["delete_book", "return_book_1", "return_book_2"])
     	}
     
     	def 'should trigger a messaging label'() {
    @@ -3139,15 +3253,17 @@ the Stub Runner server. It will be available at port 8750<
     }

    As you can see we want to start a Stub Runner Boot server @EnableStubRunnerServer, enable Eureka client @EnableEurekaClient and we want to have the stub runner feature turned on @AutoConfigureStubRunner.

    Now let’s assume that we want to start this application so that the stubs get automatically registered. We can do it by running the app java -jar ${SYSTEM_PROPS} stub-runner-boot-eureka-example.jar where - ${SYSTEM_PROPS} would contain the following list of properties

    -Dstubrunner.repositoryRoot=http://repo.spring.io/snapshots (1)
    --Dstubrunner.cloud.stubbed.discovery.enabled=false (2)
    --Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.cloud.contract.verifier.stubs:bootService (3)
    --Dstubrunner.idsToServiceIds.fraudDetectionServer=someNameThatShouldMapFraudDetectionServer (4)
    -
    -(1) - we tell Stub Runner where all the stubs reside
    -(2) - we don't want the default behaviour where the discovery service is stubbed. That's why the stub registration will be picked
    -(3) - we provide a list of stubs to download
    -(4) - we provide a list of artifactId to serviceId mapping

    That way your deployed application can send requests to started WireMock servers via the service + ${SYSTEM_PROPS} would contain the following list of properties

    * -Dstubrunner.repositoryRoot=http://repo.spring.io/snapshots (1)
    +* -Dstubrunner.cloud.stubbed.discovery.enabled=false (2)
    +* -Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.
    +* springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.
    +* cloud.contract.verifier.stubs:bootService (3)
    +* -Dstubrunner.idsToServiceIds.fraudDetectionServer=
    +* someNameThatShouldMapFraudDetectionServer (4)
    +*
    +* (1) - we tell Stub Runner where all the stubs reside (2) - we don't want the default
    +* behaviour where the discovery service is stubbed. That's why the stub registration will
    +* be picked (3) - we provide a list of stubs to download (4) - we provide a list of

    That way your deployed application can send requests to started WireMock servers via the service discovery. Most likely points 1-3 could be set by default in application.yml cause they are not likely to change. That way you can provide only the list of stubs to download whenever you start the Stub Runner Boot.

    6.7 Stubs Per Consumer

    There are cases in which 2 consumers of the same endpoint want to have 2 different responses.

    [Tip]Tip

    This approach also allows you to immediately know which consumer is using which part of your API. @@ -3250,6 +3366,11 @@ That way the only remaining framework is Spring AMQP.

    import java.util.Collection; import java.util.Map; +/** + * Contract for triggering stub messages. + * + * @author Marcin Grzejszczak + */ public interface StubTrigger { /** @@ -3257,6 +3378,8 @@ That way the only remaining framework is Spring AMQP.

    boolean trigger(String ivyNotation, String labelName); @@ -3265,6 +3388,7 @@ That way the only remaining framework is Spring AMQP.

    boolean trigger(String labelName); @@ -3278,9 +3402,8 @@ That way the only remaining framework is Spring AMQP.

    boolean trigger(); /** - * Returns a mapping of ivy notation of a dependency to all the labels it has. - * * Feature related to messaging. + * @return a mapping of ivy notation of a dependency to all the labels it has. */ Map<String, Collection<String>> labels(); @@ -3341,9 +3464,11 @@ Remember to annotate your test class with @AutoConfigureSt } }

    Scenario 1 (no input message)

    So as to trigger a message via the return_book_1 label we’ll use the StubTigger interface as follows

    stubFinder.trigger('return_book_1')

    Next we’ll want to listen to the output of the message sent to jms:output

    Exchange receivedMessage = consumerTemplate.receive('jms:output', 5000)

    And the received message would pass the following assertions

    receivedMessage != null
     assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
    -receivedMessage.in.headers.get('BOOK-NAME') == 'foo'

    Scenario 2 (output triggered by input)

    Since the route is set for you it’s enough to just send a message to the jms:output destination.

    producerTemplate.sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header'])

    Next we’ll want to listen to the output of the message sent to jms:output

    Exchange receivedMessage = consumerTemplate.receive('jms:output', 5000)

    And the received message would pass the following assertions

    receivedMessage != null
    +receivedMessage.in.headers.get('BOOK-NAME') == 'foo'

    Scenario 2 (output triggered by input)

    Since the route is set for you it’s enough to just send a message to the jms:output destination.

    producerTemplate.
    +		sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header'])

    Next we’ll want to listen to the output of the message sent to jms:output

    Exchange receivedMessage = consumerTemplate.receive('jms:output', 5000)

    And the received message would pass the following assertions

    receivedMessage != null
     assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
    -receivedMessage.in.headers.get('BOOK-NAME') == 'foo'

    Scenario 3 (input with no output)

    Since the route is set for you it’s enough to just send a message to the jms:output destination.

    producerTemplate.sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header'])

    7.3 Stub Runner Integration

    Spring Cloud Contract Verifier Stub Runner’s messaging module gives you an easy way to +receivedMessage.in.headers.get('BOOK-NAME') == 'foo'

    Scenario 3 (input with no output)

    Since the route is set for you it’s enough to just send a message to the jms:output destination.

    producerTemplate.
    +		sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header'])

    7.3 Stub Runner Integration

    Spring Cloud Contract Verifier Stub Runner’s messaging module gives you an easy way to integrate with Spring Integration. For the provided artifacts, it automatically downloads the stubs and registers the required routes.

    7.3.1 Adding the Runner to the Project

    You can have both Spring Integration and Spring Cloud Contract Stub Runner on the classpath. Remember to annotate your test class with @AutoConfigureStubRunner.

    7.3.2 Disabling the functionality

    If you need to disable this functionality, set the @@ -3399,9 +3524,9 @@ classpath. Remember to annotate your test class with @Auto } } }

    and the following Spring Integration Route:

    <?xml version="1.0" encoding="UTF-8"?>
    -<beans:beans xmlns="http://www.springframework.org/schema/integration"
    -			 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    +<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     			 xmlns:beans="http://www.springframework.org/schema/beans"
    +			 xmlns="http://www.springframework.org/schema/integration"
     			 xsi:schemaLocation="http://www.springframework.org/schema/beans
     			http://www.springframework.org/schema/beans/spring-beans.xsd
     			http://www.springframework.org/schema/integration
    @@ -3534,29 +3659,29 @@ to disable them explicitly by setting the  stubrunner.stre
     │   └── MANIFEST.MF
     └── contracts
         └── shouldProduceValidPersonData.groovy

    Consider the following contract:

    Contract.make {
    -    // Human readable description
    -    description 'Should produce valid person data'
    -    // Label by means of which the output message can be triggered
    -    label 'contract-test.person.created.event'
    -    // input to the contract
    -    input {
    -        // the contract will be triggered by a method
    -        triggeredBy('createPerson()')
    -    }
    -    // output message of the contract
    -    outputMessage {
    -        // destination to which the output message will be sent
    -        sentTo 'contract-test.exchange'
    -        headers {
    -            header('contentType': 'application/json')
    -            header('__TypeId__': 'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person')
    -        }
    -        // the body of the output message
    -        body ([
    -                id: $(consumer(9), producer(regex("[0-9]+"))),
    -                name: "me"
    -        ])
    -    }
    +	// Human readable description
    +	description 'Should produce valid person data'
    +	// Label by means of which the output message can be triggered
    +	label 'contract-test.person.created.event'
    +	// input to the contract
    +	input {
    +		// the contract will be triggered by a method
    +		triggeredBy('createPerson()')
    +	}
    +	// output message of the contract
    +	outputMessage {
    +		// destination to which the output message will be sent
    +		sentTo 'contract-test.exchange'
    +		headers {
    +			header('contentType': 'application/json')
    +			header('__TypeId__': 'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person')
    +		}
    +		// the body of the output message
    +		body([
    +				id  : $(consumer(9), producer(regex("[0-9]+"))),
    +				name: "me"
    +		])
    +	}
     }

    Now consider the following Spring configuration:

    stubrunner:
       repositoryRoot: classpath:m2repo/repository/
       ids: org.springframework.cloud.contract.verifier.stubs.amqp:spring-cloud-contract-amqp-test:0.4.0-SNAPSHOT:stubs
    @@ -3581,7 +3706,7 @@ definition is matched and invoked with the contract message.

    return container;
    -}

    Also, the following annotated listener matches and is invoked:

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "test.queue"), exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true")))
    +}

    Also, the following annotated listener matches and is invoked:

    @RabbitListener(bindings = @QueueBinding(value = @Queue("test.queue"), exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true")))
     public void handlePerson(Person person) {
     	this.person = person;
     }
    [Note]Note

    The message is directly handed over to the onMessage method of the @@ -3654,8 +3779,8 @@ You can also provide the assertJsonSize property in properly when using the Groovy DSL and the value(consumer(…​), producer(…​)) notation in GString. That is why you should use the Groovy Map notation.

    8.2 Common Top-Level elements

    The following sections describe the most common top-level elements:

    8.2.1 Description

    You can add a description to your contract. The description is arbitrary text. The following code shows an example:

    Groovy DSL.  -

    		org.springframework.cloud.contract.spec.Contract.make {
    -			description('''
    +

    			org.springframework.cloud.contract.spec.Contract.make {
    +				description('''
     given:
     	An input
     when:
    @@ -3663,7 +3788,7 @@ when:
     then:
     	Output
     ''')
    -		}

    + }

    YAML. 

    description: Some description
     name: some name
    @@ -3741,7 +3866,23 @@ following resources in our project.

    └─
                     ├── readFromFile.groovy
                     ├── request.json
                     └── response.json

    Further assume that your contract is as follows:

    Groovy DSL.  -

    import org.springframework.cloud.contract.spec.Contract
    +

    /*
    + * Copyright 2013-2019 the original author or authors.
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *      http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +
    +import org.springframework.cloud.contract.spec.Contract
     
     Contract.make {
     	request {
    @@ -3797,16 +3938,16 @@ Contract.make {
     }

    YAML. 

    request:
    -    url: /1
    -    method: PUT
    -    headers:
    -        Content-Type: application/octet-stream
    -    bodyFromFileAsBytes: request.pdf
    +  url: /1
    +  method: PUT
    +  headers:
    +    Content-Type: application/octet-stream
    +  bodyFromFileAsBytes: request.pdf
     response:
    -    status: 200
    -    bodyFromFileAsBytes: response.pdf
    -    headers:
    -        Content-Type: application/octet-stream

    + status: 200 + bodyFromFileAsBytes: response.pdf + headers: + Content-Type: application/octet-stream

    [Important]Important

    You should use this approach whenever you want to work with binary payloads both for HTTP and messaging.

    8.2.5 HTTP Top-Level Elements

    The following methods can be called in the top-level closure of a contract definition. request and response are mandatory. priority is optional.

    Groovy DSL. 

    org.springframework.cloud.contract.spec.Contract.make {
    @@ -4065,7 +4206,7 @@ body:
         Content-Type: multipart/form-data;boundary=AaB03x
       multipart:
         params:
    -    # key (parameter name), value (parameter value) pair
    +      # key (parameter name), value (parameter value) pair
           formParameter: '"formParameterValue"'
           someBooleanParameter: true
         named:
    @@ -4199,25 +4340,25 @@ need to use patterns and not exact values both for your test and your server sid
     }

    You can also provide only one side of the communication with a regular expression. If you do so, then the contract engine automatically provides the generated string that matches the provided regular expression. The following code shows an example:

    org.springframework.cloud.contract.spec.Contract.make {
    -    request {
    -        method 'PUT'
    -        url value(consumer(regex('/foo/[0-9]{5}')))
    -        body([
    -                requestElement: $(consumer(regex('[0-9]{5}')))
    -        ])
    -        headers {
    -            header('header', $(consumer(regex('application\\/vnd\\.fraud\\.v1\\+json;.*'))))
    -        }
    -    }
    -    response {
    -        status OK()
    -        body([
    -                responseElement: $(producer(regex('[0-9]{7}')))
    -        ])
    -        headers {
    -            contentType("application/vnd.fraud.v1+json")
    -        }
    -    }
    +	request {
    +		method 'PUT'
    +		url value(consumer(regex('/foo/[0-9]{5}')))
    +		body([
    +				requestElement: $(consumer(regex('[0-9]{5}')))
    +		])
    +		headers {
    +			header('header', $(consumer(regex('application\\/vnd\\.fraud\\.v1\\+json;.*'))))
    +		}
    +	}
    +	response {
    +		status OK()
    +		body([
    +				responseElement: $(producer(regex('[0-9]{7}')))
    +		])
    +		headers {
    +			contentType("application/vnd.fraud.v1+json")
    +		}
    +	}
     }

    In the preceding example, the opposite side of the communication has the respective data generated for request and response.

    Spring Cloud Contract comes with a series of predefined regular expressions that you can use in your contracts, as shown in the following example:

    protected static final Pattern TRUE_OR_FALSE = Pattern.compile(/(true|false)/)
    @@ -4228,21 +4369,29 @@ use in your contracts, as shown in the following example:

    protected static final Pattern POSITIVE_INT = Pattern.compile('([1-9]\\d*)')
     protected static final Pattern DOUBLE = Pattern.compile('-?(\\d*\\.\\d+)')
     protected static final Pattern HEX = Pattern.compile('[a-fA-F0-9]+')
    -protected static final Pattern IP_ADDRESS = Pattern.compile('([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])')
    -protected static final Pattern HOSTNAME_PATTERN = Pattern.compile('((http[s]?|ftp):/)/?([^:/\\s]+)(:[0-9]{1,5})?')
    -protected static final Pattern EMAIL = Pattern.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}')
    +protected static final Pattern IP_ADDRESS = Pattern.
    +		compile('([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])')
    +protected static final Pattern HOSTNAME_PATTERN = Pattern.
    +		compile('((http[s]?|ftp):/)/?([^:/\\s]+)(:[0-9]{1,5})?')
    +protected static final Pattern EMAIL = Pattern.
    +		compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}')
     protected static final Pattern URL = UrlHelper.URL
     protected static final Pattern HTTPS_URL = UrlHelper.HTTPS_URL
    -protected static final Pattern UUID = Pattern.compile('[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}')
    -protected static final Pattern ANY_DATE = Pattern.compile('(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])')
    -protected static final Pattern ANY_DATE_TIME = Pattern.compile('([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])')
    -protected static final Pattern ANY_TIME = Pattern.compile('(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])')
    +protected static final Pattern UUID = Pattern.
    +		compile('[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}')
    +protected static final Pattern ANY_DATE = Pattern.
    +		compile('(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])')
    +protected static final Pattern ANY_DATE_TIME = Pattern.
    +		compile('([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])')
    +protected static final Pattern ANY_TIME = Pattern.
    +		compile('(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])')
     protected static final Pattern NON_EMPTY = Pattern.compile(/[\S\s]+/)
     protected static final Pattern NON_BLANK = Pattern.compile(/^\s*\S[\S\s]*/)
    -protected static final Pattern ISO8601_WITH_OFFSET = Pattern.compile(/([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d{3})?(Z|[+-][01]\d:[0-5]\d)/)
    +protected static final Pattern ISO8601_WITH_OFFSET = Pattern.
    +		compile(/([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d{3})?(Z|[+-][01]\d:[0-5]\d)/)
     
    -protected static Pattern anyOf(String... values){
    -	return Pattern.compile(values.collect({"^$it\$"}).join("|"))
    +protected static Pattern anyOf(String... values) {
    +	return Pattern.compile(values.collect({ "^$it\$" }).join("|"))
     }
     
     RegexProperty onlyAlphaUnicode() {
    @@ -4293,7 +4442,7 @@ RegexProperty httpsUrl() {
     	return new RegexProperty(HTTPS_URL).asString()
     }
     
    -RegexProperty uuid(){
    +RegexProperty uuid() {
     	return new RegexProperty(UUID).asString()
     }
     
    @@ -4320,28 +4469,28 @@ RegexProperty nonEmpty() {
     RegexProperty nonBlank() {
     	return new RegexProperty(NON_BLANK).asString()
     }

    In your contract, you can use it as shown in the following example:

    Contract dslWithOptionalsInString = Contract.make {
    -    priority 1
    -    request {
    -        method POST()
    -        url '/users/password'
    -        headers {
    -            contentType(applicationJson())
    -        }
    -        body(
    -                email: $(consumer(optional(regex(email()))), producer('abc@abc.com')),
    -                callback_url: $(consumer(regex(hostname())), producer('http://partners.com'))
    -        )
    -    }
    -    response {
    -        status 404
    -        headers {
    -            contentType(applicationJson())
    -        }
    -        body(
    -                code: value(consumer("123123"), producer(optional("123123"))),
    -                message: "User not found by email = [${value(producer(regex(email())), consumer('not.existing@user.com'))}]"
    -        )
    -    }
    +	priority 1
    +	request {
    +		method POST()
    +		url '/users/password'
    +		headers {
    +			contentType(applicationJson())
    +		}
    +		body(
    +				email: $(consumer(optional(regex(email()))), producer('abc@abc.com')),
    +				callback_url: $(consumer(regex(hostname())), producer('http://partners.com'))
    +		)
    +	}
    +	response {
    +		status 404
    +		headers {
    +			contentType(applicationJson())
    +		}
    +		body(
    +				code: value(consumer("123123"), producer(optional("123123"))),
    +				message: "User not found by email = [${value(producer(regex(email())), consumer('not.existing@user.com'))}]"
    +		)
    +	}
     }

    To make matters even simpler you can use a set of predefined objects that will automatically assume that you want a regular expression to be passed. All of those methods start with any prefix:

    T anyAlphaUnicode()
     
    @@ -4391,25 +4540,25 @@ T anyOf(String... values)

    and this is an example of how you can referenc outputMessage { sentTo 'topic.rateablequote' body([ - alpha: $(anyAlphaUnicode()), - number: $(anyNumber()), - anInteger: $(anyInteger()), - positiveInt: $(anyPositiveInt()), - aDouble: $(anyDouble()), - aBoolean: $(aBoolean()), - ip: $(anyIpAddress()), - hostname: $(anyHostname()), - email: $(anyEmail()), - url: $(anyUrl()), - httpsUrl: $(anyHttpsUrl()), - uuid: $(anyUuid()), - date: $(anyDate()), - dateTime: $(anyDateTime()), - time: $(anyTime()), + alpha : $(anyAlphaUnicode()), + number : $(anyNumber()), + anInteger : $(anyInteger()), + positiveInt : $(anyPositiveInt()), + aDouble : $(anyDouble()), + aBoolean : $(aBoolean()), + ip : $(anyIpAddress()), + hostname : $(anyHostname()), + email : $(anyEmail()), + url : $(anyUrl()), + httpsUrl : $(anyHttpsUrl()), + uuid : $(anyUuid()), + date : $(anyDate()), + dateTime : $(anyDateTime()), + time : $(anyTime()), iso8601WithOffset: $(anyIso8601WithOffset()), - nonBlankString: $(anyNonBlankString()), - nonEmptyString: $(anyNonEmptyString()), - anyOf: $(anyOf('foo', 'bar')) + nonBlankString : $(anyNonBlankString()), + nonEmptyString : $(anyNonEmptyString()), + anyOf : $(anyOf('foo', 'bar')) ]) } }

    8.5.3 Passing Optional Parameters

    [Important]Important

    This section is valid only for Groovy DSL. Check out the @@ -4437,7 +4586,7 @@ optional parameters only for the following:

      By wrapping a part of the body with the optional() method, you create a regular -expression that must be present 0 or more times.

      If you use Spock for, the following test would be generated from the previous example:

      """
      +expression that must be present 0 or more times.

      If you use Spock for, the following test would be generated from the previous example:

      					"""
        given:
         def request = given()
           .header("Content-Type", "application/json")
      @@ -4453,7 +4602,7 @@ expression that must be present 0 or more times.

      If you use Spock for, the and: DocumentContext parsedJson = JsonPath.parse(response.body.asString()) assertThatJson(parsedJson).field("['code']").matches("(123123)?") -"""

      The following stub would also be generated:

      '''
      +"""

      The following stub would also be generated:

      					'''
       {
         "request" : {
       	"url" : "/users/password",
      @@ -4489,13 +4638,13 @@ following code shows an example of the contract portion of the test case:

      'Content-Type': 'application/json' } body '''\ - [{ - "text": "Gonna see you at Warsaw" - }] - ''' + [{ + "text": "Gonna see you at Warsaw" + }] + ''' } response { - body ( + body( path: $(consumer('/api/12'), producer(regex('^/api/[0-9]{2}$'))), correlationId: $(consumer('1223456'), producer(execute('isProperCorrelationId($it)'))) ) @@ -4665,7 +4814,23 @@ Since we use the spring.factories extension approach, you can create an entry in org.springframework.cloud.contract.stubrunner.provider.wiremock.TestWireMockExtensions org.springframework.cloud.contract.spec.ContractConverter=\ org.springframework.cloud.contract.stubrunner.TestCustomYamlContractConverter

      The following is an example of a custom extension:

      TestWireMockExtensions.groovy.  -

      package org.springframework.cloud.contract.verifier.dsl.wiremock
      +

      /*
      + * Copyright 2013-2019 the original author or authors.
      + *
      + * Licensed under the Apache License, Version 2.0 (the "License");
      + * you may not use this file except in compliance with the License.
      + * You may obtain a copy of the License at
      + *
      + *      http://www.apache.org/licenses/LICENSE-2.0
      + *
      + * Unless required by applicable law or agreed to in writing, software
      + * distributed under the License is distributed on an "AS IS" BASIS,
      + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      + * See the License for the specific language governing permissions and
      + * limitations under the License.
      + */
      +
      +package org.springframework.cloud.contract.verifier.dsl.wiremock
       
       import com.github.tomakehurst.wiremock.extension.Extension
       
      @@ -4988,7 +5153,7 @@ response:
           valueWithMinEmpty: []
           valueWithMaxEmpty: []
           key:
      -      'complex.key' : 'foo'
      +      'complex.key': 'foo'
           nulValue: null
         matchers:
           headers:
      @@ -5102,7 +5267,7 @@ separates the autogenerated assertions and the assertion from matchers):

      assertThatValueIsANumber. This method must be defined in the test base class or be
       statically imported to your tests. Notice that the byCommand call was converted to
       assertThatValueIsANumber(parsedJson.read("$.duck"));. That means that the engine took
      -the method name and passed the proper JSON path as a parameter to it.

    The resulting WireMock stub is in the following example:

    				'''
    +the method name and passed the proper JSON path as a parameter to it.

    The resulting WireMock stub is in the following example:

    					'''
     {
       "request" : {
         "urlPath" : "/get",
    @@ -5203,7 +5368,7 @@ asserted. In order to fix this, you should apply the assertion to the whole byCommand(…​) method.

    8.6 JAX-RS Support

    The Spring Cloud Contract Verifier supports the JAX-RS 2 Client API. The base class needs to define protected WebTarget webTarget and server initialization. The only option for testing JAX-RS API is to start a web server. Also, a request with a body needs to have a -content type set. Otherwise, the default of application/octet-stream gets used.

    In order to use JAX-RS mode, use the following settings:

    testMode == 'JAXRSCLIENT'

    The following example shows a generated test API:

    '''
    +content type set. Otherwise, the default of application/octet-stream gets used.

    In order to use JAX-RS mode, use the following settings:

    testMode == 'JAXRSCLIENT'

    The following example shows a generated test API:

    					'''
      // when:
       Response response = webTarget
         .path("/users")
    @@ -5372,19 +5537,19 @@ as a String or GString
     both request and response. In place of the jsonPath(…​) method, the org.springframework.cloud.contract.spec.internal.BodyMatchers.xPath
     method should be used, with the desired xPath provided as the first argument
     and the appropriate MatchingType as second. All the body matchers apart from byType() are supported.

    Here is an example of a Groovy DSL contract with XML response body:

    					Contract.make {
    -				request {
    -					method GET()
    -					urlPath '/get'
    -					headers {
    -						contentType(applicationXml())
    -					}
    -				}
    -				response {
    -					status(OK())
    -					headers {
    -						contentType(applicationXml())
    -					}
    -					body """
    +						request {
    +							method GET()
    +							urlPath '/get'
    +							headers {
    +								contentType(applicationXml())
    +							}
    +						}
    +						response {
    +							status(OK())
    +							headers {
    +								contentType(applicationXml())
    +							}
    +							body """
     <test>
     <duck type='xtype'>123</duck>
     <alpha>abc</alpha>
    @@ -5401,22 +5566,22 @@ and the appropriate MatchingType as second. All the
     <valueWithoutAMatcher>foo</valueWithoutAMatcher>
     <key><complex>foo</complex></key>
     </test>"""
    -					bodyMatchers {
    -						xPath('/test/duck/text()', byRegex("[0-9]{3}"))
    -						xPath('/test/duck/text()', byCommand('test($it)'))
    -						xPath('/test/duck/xxx', byNull())
    -						xPath('/test/duck/text()', byEquality())
    -						xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode()))
    -						xPath('/test/alpha/text()', byEquality())
    -						xPath('/test/number/text()', byRegex(number()))
    -						xPath('/test/date/text()', byDate())
    -						xPath('/test/dateTime/text()', byTimestamp())
    -						xPath('/test/time/text()', byTime())
    -						xPath('/test/*/complex/text()', byEquality())
    -						xPath('/test/duck/@type', byEquality())
    -					}
    -				}
    -			}

    And below is an example of a YAML contract with XML request and response bodies:

    include::{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml

    Here is an example of an automatically generated test for XML response body:

    @Test
    +							bodyMatchers {
    +								xPath('/test/duck/text()', byRegex("[0-9]{3}"))
    +								xPath('/test/duck/text()', byCommand('test($it)'))
    +								xPath('/test/duck/xxx', byNull())
    +								xPath('/test/duck/text()', byEquality())
    +								xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode()))
    +								xPath('/test/alpha/text()', byEquality())
    +								xPath('/test/number/text()', byRegex(number()))
    +								xPath('/test/date/text()', byDate())
    +								xPath('/test/dateTime/text()', byTimestamp())
    +								xPath('/test/time/text()', byTime())
    +								xPath('/test/*/complex/text()', byEquality())
    +								xPath('/test/duck/@type', byEquality())
    +							}
    +						}
    +					}

    And below is an example of a YAML contract with XML request and response bodies:

    include::{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml

    Here is an example of an automatically generated test for XML response body:

    @Test
     public void validate_xmlMatches() throws Exception {
     	// given:
     	MockMvcRequestSpecification request = given()
    @@ -5497,7 +5662,7 @@ example:

    Groovy DSL.  messageFrom('input') // has the following body messageBody([ - bookName: 'foo' + bookName: 'foo' ]) // and the following headers messageHeaders { @@ -5507,7 +5672,7 @@ example:

    Groovy DSL.  outputMessage { sentTo('output') body([ - bookName: 'foo' + bookName: 'foo' ]) headers { header('BOOK-NAME', 'foo') @@ -5546,24 +5711,24 @@ generates a test that sends the input message to the defined destination. On the use those paradigms in messaging. In addition, Spring Cloud Contract Verifier also provides the consumer and producer methods, as presented in the following example (note that you can use either $ or value methods to provide consumer and producer -parts):

    Contract.make {
    -	label 'some_label'
    -	input {
    -		messageFrom value(consumer('jms:output'), producer('jms:input'))
    -		messageBody([
    -				bookName: 'foo'
    -		])
    -		messageHeaders {
    -			header('sample', 'header')
    -		}
    -	}
    -	outputMessage {
    -		sentTo $(consumer('jms:input'), producer('jms:output'))
    -		body([
    -				bookName: 'foo'
    -		])
    -	}
    -}

    8.11.4 Common

    In the input or outputMessage section you can call assertThat with the name +parts):

    					Contract.make {
    +						label 'some_label'
    +						input {
    +							messageFrom value(consumer('jms:output'), producer('jms:input'))
    +							messageBody([
    +									bookName: 'foo'
    +							])
    +							messageHeaders {
    +								header('sample', 'header')
    +							}
    +						}
    +						outputMessage {
    +							sentTo $(consumer('jms:input'), producer('jms:output'))
    +							body([
    +									bookName: 'foo'
    +							])
    +						}
    +					}

    8.11.4 Common

    In the input or outputMessage section you can call assertThat with the name of a method (e.g. assertThatMessageIsOnTheQueue()) that you have defined in the base class or in a static import. Spring Cloud Contract will execute that method in the generated test.

    8.12 Multiple Contracts in One File

    You can define multiple contracts in one file. Such a contract might resemble the @@ -5571,25 +5736,25 @@ following example:

    Groovy DSL. 

    import org.springframework.cloud.contract.spec.Contract
     
     [
    -        Contract.make {
    -            name("should post a user")
    -            request {
    -                method 'POST'
    -                url('/users/1')
    -            }
    -            response {
    -                status OK()
    -            }
    -        },
    -        Contract.make {
    -            request {
    -                method 'POST'
    -                url('/users/2')
    -            }
    -            response {
    -                status OK()
    -            }
    -        }
    +	Contract.make {
    +		name("should post a user")
    +		request {
    +			method 'POST'
    +			url('/users/1')
    +		}
    +		response {
    +			status OK()
    +		}
    +	},
    +	Contract.make {
    +		request {
    +			method 'POST'
    +			url('/users/2')
    +		}
    +		response {
    +			status OK()
    +		}
    +	}
     ]

    YAML. 

    ---
    @@ -5679,7 +5844,6 @@ testCompile 'org
     

    Next you need to make some changes to your base class like the following example.

    package com.example.fraud;
     
     import io.restassured.module.mockmvc.RestAssuredMockMvc;
    -
     import org.junit.Before;
     import org.junit.Rule;
     import org.junit.rules.TestName;
    @@ -5704,29 +5868,32 @@ testCompile 'org
     	@Rule
     	public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(OUTPUT);
     
    -	@Rule public TestName testName = new TestName();
    +	@Rule
    +	public TestName testName = new TestName();
     
     	@Autowired
     	private WebApplicationContext context;
     
     	@Before
     	public void setup() {
    -	RestAssuredMockMvc.mockMvc(MockMvcBuilders.webAppContextSetup(this.context)
    -			.apply(documentationConfiguration(this.restDocumentation))
    -			.alwaysDo(document(getClass().getSimpleName() + "_" + testName.getMethodName()))
    -			.build());
    +		RestAssuredMockMvc.mockMvc(MockMvcBuilders.webAppContextSetup(this.context)
    +				.apply(documentationConfiguration(this.restDocumentation))
    +				.alwaysDo(document(
    +						getClass().getSimpleName() + "_" + testName.getMethodName()))
    +				.build());
     	}
     
     	protected void assertThatRejectionReasonIsNull(Object rejectionReason) {
     		assert rejectionReason == null;
     	}
    -}
    -// end::base_class[]

    In case you are using the standalone setup, you can set up RestAssuredMockMvc like this:

    package com.example.fraud;
    +
    +}

    In case you are using the standalone setup, you can set up RestAssuredMockMvc like this:

    package com.example.fraud;
     
     import io.restassured.module.mockmvc.RestAssuredMockMvc;
     import org.junit.Before;
     import org.junit.Rule;
     import org.junit.rules.TestName;
    +
     import org.springframework.restdocs.JUnitRestDocumentation;
     import org.springframework.test.web.servlet.setup.MockMvcBuilders;
     
    @@ -5740,17 +5907,19 @@ testCompile 'org
     	@Rule
     	public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(OUTPUT);
     
    -	@Rule public TestName testName = new TestName();
    +	@Rule
    +	public TestName testName = new TestName();
     
     	@Before
     	public void setup() {
    -		RestAssuredMockMvc.standaloneSetup(MockMvcBuilders.standaloneSetup(new FraudDetectionController())
    +		RestAssuredMockMvc.standaloneSetup(MockMvcBuilders
    +				.standaloneSetup(new FraudDetectionController())
     				.apply(documentationConfiguration(this.restDocumentation))
    -				.alwaysDo(document(getClass().getSimpleName() + "_" + testName.getMethodName())));
    +				.alwaysDo(document(
    +						getClass().getSimpleName() + "_" + testName.getMethodName())));
     	}
     
    -}
    -// end::base_class[]
    [Tip]Tip

    You don’t need to specify the output directory for the generated snippets since version 1.2.0.RELEASE of Spring REST Docs.

    9. Customization

    [Important]Important

    This section is valid only for Groovy DSL

    You can customize the Spring Cloud Contract Verifier by extending the DSL, as shown in +}

    [Tip]Tip

    You don’t need to specify the output directory for the generated snippets since version 1.2.0.RELEASE of Spring REST Docs.

    9. Customization

    [Important]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.

    9.1 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:

    • Creating a JAR with reusable classes.
    • Referencing of these classes in the DSLs.

    You can find the full example here.

    9.1.1 Common JAR

    The following examples show three classes that can be reused in the DSLs.

    PatternUtils contains functions used by both the consumer and the producer.

    package com.example;
    @@ -5976,7 +6145,7 @@ structure converter. The following code listing shows the 
      * Converter to be used to convert FROM {@link File} TO {@link Contract}
      * and from {@link Contract} to {@code T}
      *
    - * @param <T> - type to which we want to convert the contract
    + * @param <T >     - type to which we want to convert the contract
      *
      * @author Marcin Grzejszczak
      * @since 1.1.0
    @@ -6062,7 +6231,7 @@ set a metaData entry in the Pact file, with key "combine": "AND"
                 }
               },
    -          "body" : {
    +          "body": {
                 "$.clientId": {
                   "matchers": [
                     {
    @@ -6197,15 +6366,31 @@ current Pact version that you use.

    Maven. 

    testCompile "org.springframework.cloud:spring-cloud-contract-pact"

    10.2 Using the Custom Test Generator

    If you want to generate tests for languages other than Java or you are not happy with the way the verifier builds Java tests, you can register your own implementation.

    The SingleTestGenerator interface lets you register your own implementation. The -following code listing shows the SingleTestGenerator interface:

    	 *
    -	 * @param properties                    - properties passed to the plugin
    -	 * @param listOfFiles                   - list of parsed contracts with additional metadata
    -	 * @param className                     - the name of the generated test class
    -	 * @param classPackage                  - the name of the package in which the test class should be stored
    -	 * @param includedDirectoryRelativePath - relative path to the included directory
    -	 * @return contents of a single test class
    -	 * @deprecated use {@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)}
    -	 */
    +following code listing shows the SingleTestGenerator interface:

    package org.springframework.cloud.contract.verifier.builder
    +
    +
    +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
    +import org.springframework.cloud.contract.verifier.file.ContractMetadata
    +
    +/**
    + * Builds a single test.
    + *
    + * @since 1.1.0
    + */
    +trait SingleTestGenerator {
    +
    +	/**
    +	 * Creates contents of a single test class in which all test scenarios from
    +	 * the contract metadata should be placed.
    +	 *
    +	 * @param properties - properties passed to the plugin
    +	 * @param listOfFiles - list of parsed contracts with additional metadata
    +	 * @param className - the name of the generated test class
    +	 * @param classPackage - the name of the package in which the test class should be stored
    +	 * @param includedDirectoryRelativePath - relative path to the included directory
    +	 * @return contents of a single test class
    +	 * @deprecated use{@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)}
    +	 */
     	@Deprecated
     	abstract String buildClass(ContractVerifierConfigProperties properties,
     			Collection<ContractMetadata> listOfFiles, String className, String classPackage, String includedDirectoryRelativePath)
    @@ -6214,15 +6399,18 @@ following code listing shows the SingleTestGenerator
     	String buildClass(ContractVerifierConfigProperties properties,
     			Collection<ContractMetadata> listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) {
    -		return buildClass(properties, listOfFiles, generatedClassData.className, generatedClassData.classPackage, includedDirectoryRelativePath)
    +		String className = generatedClassData.className
    +		String classPackage = generatedClassData.classPackage
    +		String path = includedDirectoryRelativePath
    +		return buildClass(properties, listOfFiles, className, classPackage, path)
     	}
     
     	/**
    @@ -6251,6 +6439,7 @@ own implementation of the StubGenerator interface.
     StubGenerator interface:

    package org.springframework.cloud.contract.verifier.converter
     
     import groovy.transform.CompileStatic
    +
     import org.springframework.cloud.contract.spec.Contract
     import org.springframework.cloud.contract.verifier.file.ContractMetadata
     
    @@ -6263,18 +6452,18 @@ own implementation of the StubGenerator interface.
     interface StubGenerator {
     
     	/**
    -	 * Returns {@code true} if the converter can handle the file to convert it into a stub.
    +	 * @return {@code true} if the converter can handle the file to convert it into a stub.
     	 */
     	boolean canHandleFileName(String fileName)
     
     	/**
    -	 * Returns the collection of converted contracts into stubs. One contract can
    +	 * @return the collection of converted contracts into stubs. One contract can
     	 * result in multiple stubs.
     	 */
     	Map<Contract, String> convertContents(String rootName, ContractMetadata content)
     
     	/**
    -	 * Returns the name of the converted stub file. If you have multiple contracts
    +	 * @return the name of the converted stub file. If you have multiple contracts
     	 * in a single file then a prefix will be added to the generated file. If you
     	 * provide the {@link Contract#name} field then that field will override the
     	 * generated file name.
    @@ -6344,17 +6533,19 @@ HTTP Stub server implementation, which might resemble the following example:

    @Override HttpServerStub registerMappings(Collection<File> stubFiles) { List<RunnerSetting> settings = stubFiles.findAll { it.name.endsWith("json") } - .collect { + .collect { log.info("Trying to parse [${it.name}]") try { - return RunnerSetting.aRunnerSetting().withStream(it.newInputStream()).build() - } catch (Exception e) { + return RunnerSetting.aRunnerSetting().withStream(it.newInputStream()). + build() + } + catch (Exception e) { log.warn("Exception occurred while trying to parse file [${it.name}]", e) return null } }.findAll { it } this.runner = JsonRunner.newJsonRunnerWithSetting(settings, - HttpArgs.httpArgs().withPort(this.port).build()) + HttpArgs.httpArgs().withPort(this.port).build()) this.runner.run() this.started = true return this @@ -6427,6 +6618,12 @@ your test. The following code shows an example:

    <
     	@Autowired
     	private Service service;
     
    +	@Before
    +	public void setup() {
    +		this.service.setBase("http://localhost:"
    +				+ this.environment.getProperty("wiremock.server.port"));
    +	}
    +
     	// Using the WireMock APIs in the normal way:
     	@Test
     	public void contextLoads() throws Exception {
    @@ -6437,8 +6634,7 @@ your test. The following code shows an example:

    <
     		assertThat(this.service.go()).isEqualTo("Hello World!");
     	}
     
    -}
    -// end::wiremock_test2[]

    To start the stub server on a different port use (for example), +}

    To start the stub server on a different port use (for example), @AutoConfigureWireMock(port=9999). For a random port, use a value of 0. The stub server port can be bound in the test application context with the "wiremock.server.port" property. Using @AutoConfigureWireMock adds a bean of type WiremockConfiguration to @@ -6486,15 +6682,15 @@ instance, as shown in the following example:

    
     	public static WireMockClassRule wiremock = new WireMockClassRule(
     			WireMockSpring.options().dynamicPort());
     
    +	// A service that calls out over HTTP to wiremock's port
    +	@Autowired
    +	private Service service;
    +
     	@Before
     	public void setup() {
     		this.service.setBase("http://localhost:" + wiremock.port());
     	}
     
    -	// A service that calls out over HTTP to wiremock's port
    -	@Autowired
    -	private Service service;
    -
     	// Using the WireMock APIs in the normal way:
     	@Test
     	public void contextLoads() throws Exception {
    @@ -6505,8 +6701,7 @@ instance, as shown in the following example:

    
     		assertThat(this.service.go()).isEqualTo("Hello World!");
     	}
     
    -}
    -// end::wiremock_test2[]

    The @ClassRule means that the server shuts down after all the methods in this class +}

    The @ClassRule means that the server shuts down after all the methods in this class have been run.

    11.4 Relaxed SSL Validation for Rest Template

    WireMock lets you stub a "secure" server with an "https" URL protocol. If your application wants to contact that stub server in an integration test, it will find that the SSL certificates are not valid (the usual problem with self-installed certificates). diff --git a/spring-cloud-contract-maven-plugin/checkstyle.html b/spring-cloud-contract-maven-plugin/checkstyle.html index fa3e1216d6..2654b91252 100644 --- a/spring-cloud-contract-maven-plugin/checkstyle.html +++ b/spring-cloud-contract-maven-plugin/checkstyle.html @@ -285,7 +285,7 @@ 12 0 0 -582

    +539
    +18

    Rules

    @@ -364,43 +364,33 @@ - - - - - - + - + - + - + - - - - - - + @@ -409,57 +399,42 @@ - - + + - - - - - - + - + - + - + - + - + - - - - - - - - - - - +
    Severity
    blocksNeedBraces6 Error
    RightCurly 11  Error
    coding AvoidInlineConditionals 10  Error
    HiddenField 36  Error
    MagicNumber 1  Error
    design DesignForExtension 23  Error
    HideUtilityClassConstructor1 Error
    javadoc JavadocMethod5758  Error
     Error
    JavadocStyle36JavadocType2  Error
    JavadocType5 Error
    JavadocVariable 71  Error
    misc FinalParameters 63  Error
    naming ConstantName 4  Error
    sizes LineLength239244  Error
    ParameterNumber 1  Error
    whitespace FileTabCharacter 12  Error
    NoWhitespaceAfter1 Error
    OperatorWrap2 Error
    WhitespaceAroundNoWhitespaceAfter 1  Error
    @@ -467,273 +442,231 @@

    org/springframework/cloud/contract/maven/verifier/BaseClassMapping.java

    - + - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - + + + + + + + -
    Severity Category Rule Message Line
     ErrorjavadocJavadocStyleFirst sentence should end with a period.3
     Error sizes LineLength Line is longer than 80 characters (found 87).4
    20
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).12
    28
     Error javadoc JavadocVariable Missing a Javadoc comment.12
    28
     Error javadoc JavadocVariable Missing a Javadoc comment.14
    30
     Error design DesignForExtension Class 'BaseClassMapping' looks like designed for extension (can be subclassed), but the method 'getContractPackageRegex' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'BaseClassMapping' final or making the method 'getContractPackageRegex' static/final/abstract/empty, or adding allowed annotation for the method.16
    32
     Error javadoc JavadocMethod Missing a Javadoc comment.16
    32
     Error design DesignForExtension Class 'BaseClassMapping' looks like designed for extension (can be subclassed), but the method 'setContractPackageRegex' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'BaseClassMapping' final or making the method 'setContractPackageRegex' static/final/abstract/empty, or adding allowed annotation for the method.20
    36
     Error javadoc JavadocMethod Missing a Javadoc comment.20
    36
     Error misc FinalParameters Parameter contractPackageRegex should be final.20
    36
     Error coding HiddenField 'contractPackageRegex' hides a field.20
    36
     Error design DesignForExtension Class 'BaseClassMapping' looks like designed for extension (can be subclassed), but the method 'getBaseClassFQN' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'BaseClassMapping' final or making the method 'getBaseClassFQN' static/final/abstract/empty, or adding allowed annotation for the method.24
    40
     Error javadoc JavadocMethod Missing a Javadoc comment.24
    40
     Error design DesignForExtension Class 'BaseClassMapping' looks like designed for extension (can be subclassed), but the method 'setBaseClassFQN' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'BaseClassMapping' final or making the method 'setBaseClassFQN' static/final/abstract/empty, or adding allowed annotation for the method.28
    44
     Error javadoc JavadocMethod Missing a Javadoc comment.28
    44
     Error misc FinalParameters Parameter baseClassFQN should be final.28
    44
     Error coding HiddenField 'baseClassFQN' hides a field.28
    44
     Error design DesignForExtension Class 'BaseClassMapping' looks like designed for extension (can be subclassed), but the method 'equals' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'BaseClassMapping' final or making the method 'equals' static/final/abstract/empty, or adding allowed annotation for the method.32
    48
     Error misc FinalParameters Parameter o should be final.33
    49
     ErrorblocksNeedBraces'if' construct must use '{}'s.34
     ErrorblocksNeedBraces'if' construct must use '{}'s.36
     ErrorblocksNeedBraces'if' construct must use '{}'s.39
     Error sizes LineLength Line is longer than 80 characters (found 94).40
    58
     Error coding AvoidInlineConditionals Avoid inline conditionals.40
    58
     Error sizes LineLength Line is longer than 80 characters (found 94).43
    62
     Error coding AvoidInlineConditionals Avoid inline conditionals.43
    62
     Error design DesignForExtension Class 'BaseClassMapping' looks like designed for extension (can be subclassed), but the method 'hashCode' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'BaseClassMapping' final or making the method 'hashCode' static/final/abstract/empty, or adding allowed annotation for the method.48
    67
     Error coding AvoidInlineConditionals Avoid inline conditionals.51
    70
     Error coding MagicNumber '31' is a magic number.52
    71
     Error sizes LineLength Line is longer than 80 characters (found 97).53
    72
     Error coding AvoidInlineConditionals Avoid inline conditionals.53
    72
     Error design DesignForExtension Class 'BaseClassMapping' looks like designed for extension (can be subclassed), but the method 'toString' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'BaseClassMapping' final or making the method 'toString' static/final/abstract/empty, or adding allowed annotation for the method.57
     ErrorsizesLineLengthLine is longer than 80 characters (found 97).59
    76
     Error sizes LineLengthLine is longer than 80 characters (found 97).78
     ErrorsizesLineLength Line is longer than 80 characters (found 93).60
    +79

    org/springframework/cloud/contract/maven/verifier/ConvertMojo.java

    - + - + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - + @@ -745,475 +678,403 @@ - + - - + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - - - - - - + - + - + + + + + + + - + + + + + + + + + + + + + + + + + + + - + - - - - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + - - + + + + + + + + - - - - - - - + - + - + + + + + + + - - + + - - + + - - + + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - - + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + @@ -1222,508 +1083,763 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - + - - + + - - - - - - - - - - - - - - - - - - - - + + -
    Severity Category Rule Message Line
     Error sizes LineLength Line is longer than 80 characters (found 81).43
    44
     Error sizes LineLength Line is longer than 80 characters (found 86).45
    46
     Error sizes LineLength Line is longer than 80 characters (found 102).48
    51
     Error sizes LineLength Line is longer than 80 characters (found 84).51
    54
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).51
     ErrorjavadocJavadocVariableMissing a Javadoc comment.51
     ErrorjavadocJavadocVariableMissing a Javadoc comment.52
     ErrorjavadocJavadocVariableMissing a Javadoc comment.53
    54
     Error javadocjavadoc JavadocVariable Missing a Javadoc comment.56
    55
     Error javadocJavadocStyleFirst sentence should end with a period.JavadocVariableMissing a Javadoc comment.56
     ErrorjavadocJavadocVariableMissing a Javadoc comment.57
     ErrorjavadocJavadocVariableMissing a Javadoc comment. 59
     ErrorjavadocJavadocVariableMissing a Javadoc comment.61
     Error sizes LineLength Line is longer than 80 characters (found 90).60
    65
     Error sizes LineLength Line is longer than 80 characters (found 148).63
    68
     Error sizes LineLength Line is longer than 80 characters (found 93).67
    72
     Error sizes LineLength Line is longer than 80 characters (found 86).76
    81
     Error javadoc JavadocVariable Missing a Javadoc comment.81
    86
     Error sizes LineLength Line is longer than 80 characters (found 92).84
     ErrorjavadocJavadocVariableMissing a Javadoc comment.84
    89
     Error javadoc JavadocVariable Missing a Javadoc comment.87
    89
     Error javadoc JavadocVariable Missing a Javadoc comment.90
    92
     ErrorjavadocJavadocVariableMissing a Javadoc comment.95
     Error sizes LineLength Line is longer than 80 characters (found 90).94
    99
     ErrorsizesLineLengthLine is longer than 80 characters (found 87).100
     ErrorjavadocJavadocVariableMissing a Javadoc comment.106
     ErrorsizesLineLengthLine is longer than 80 characters (found 89).110
     Error sizes LineLength Line is longer than 80 characters (found 87).95
    111
     ErrorjavadocJavadocVariableMissing a Javadoc comment.101
    sizesLineLengthLine is longer than 80 characters (found 87).112
     Error sizes LineLength Line is longer than 80 characters (found 89).105
    113
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).125
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).156
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).160
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).165
     Error sizes LineLength Line is longer than 80 characters (found 87).106
    173
     Error javadocJavadocStyleExtra HTML tag found: </p>108
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).109
     ErrorjavadocJavadocStyleFirst sentence should end with a period.115
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).122
     ErrorjavadocJavadocStyleFirst sentence should end with a period.152
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).153
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).157
     ErrorjavadocJavadocStyleFirst sentence should end with a period.161
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).162
     ErrorjavadocJavadocStyleFirst sentence should end with a period.168
     ErrorsizesLineLengthLine is longer than 80 characters (found 86).170
     ErrorjavadocJavadocStyleFirst sentence should end with a period.175
     ErrorjavadocJavadocVariableMissing a Javadoc comment.181
     Errorjavadoc JavadocVariable Missing a Javadoc comment. 184
     Error javadoc JavadocMethod Missing a Javadoc comment.186
    187
     Error sizes LineLength Line is longer than 80 characters (found 85).187
    188
     Error misc FinalParameters Parameter aetherStubDownloaderFactory should be final.187
    188
     Error coding HiddenField 'aetherStubDownloaderFactory' hides a field.187
    188
     Error design DesignForExtension Class 'ConvertMojo' looks like designed for extension (can be subclassed), but the method 'execute' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'ConvertMojo' final or making the method 'execute' static/final/abstract/empty, or adding allowed annotation for the method.191
    192
     Error javadoc JavadocMethod Missing a Javadoc comment.191
    192
     Error sizes LineLength Line is longer than 80 characters (found 132).194
    195
     Error sizes LineLength Line is longer than 80 characters (found 91).201
    202
     Error sizes LineLength Line is longer than 80 characters (found 97).203
    204
     Error coding HiddenField 'contractsDirectory' hides a field.205
     ErrorsizesLineLengthLine is longer than 80 characters (found 84). 206
     Error sizes LineLengthLine is longer than 80 characters (found 91).208
    Line is longer than 80 characters (found 84).207
     Error sizes LineLengthLine is longer than 80 characters (found 105).211
    Line is longer than 80 characters (found 91).209
     Error sizes LineLengthLine is longer than 80 characters (found 87).212
     ErrorsizesLineLength Line is longer than 80 characters (found 88).216
     ErrorsizesLineLengthLine is longer than 80 characters (found 183).220
    218
     Error javadoc JavadocMethod Missing a Javadoc comment.220
    222
     Error misc FinalParameters Parameter rootPath should be final.220
    222
     ErrorsizesLineLengthLine is longer than 80 characters (found 89).223
     Error misc FinalParameters Parameter config should be final.220
    223
     Error misc FinalParameters Parameter contractsDirectory should be final.220
    223
     Error coding HiddenField 'contractsDirectory' hides a field.220
    223
     Error misc FinalParameters Parameter contractsDslDir should be final.220
     ErrorsizesLineLengthLine is longer than 80 characters (found 112).223
    224
     Error sizes LineLengthLine is longer than 80 characters (found 92).226
     ErrorjavadocJavadocMethodMissing a Javadoc comment.226
     ErrormiscFinalParametersParameter rootPath should be final.226
     ErrormiscFinalParametersParameter config should be final.226
     ErrormiscFinalParametersParameter contractsDirectory should be final.Line is longer than 80 characters (found 86). 227
     ErrorcodingHiddenField'contractsDirectory' hides a field.227
     ErrorsizesLineLengthLine is longer than 80 characters (found 105).228
     ErrorsizesLineLengthLine is longer than 80 characters (found 104).229
     ErrorsizesLineLengthLine is longer than 80 characters (found 85).230
     Error sizes LineLength Line is longer than 80 characters (found 92).234
    231
     Error javadoc JavadocMethod Missing a Javadoc comment.234
    231
     Error misc FinalParameters Parameter rootPath should be final.234
    231
     Error misc FinalParameters Parameter config should be final.234
    231
     Error misc FinalParameters Parameter contractsDirectory should be final.235
    232
     Error coding HiddenField 'contractsDirectory' hides a field.235
    232
     Error sizes LineLengthLine is longer than 80 characters (found 102).236
    Line is longer than 80 characters (found 96).235
     ErrorwhitespaceOperatorWrap'?' should be on a new line.sizesLineLengthLine is longer than 80 characters (found 92). 236
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).240
     ErrorjavadocJavadocMethodMissing a Javadoc comment.240
     ErrormiscFinalParametersParameter rootPath should be final.240
     ErrormiscFinalParametersParameter config should be final.240
     ErrormiscFinalParametersParameter contractsDirectory should be final.241
     ErrorcodingHiddenField'contractsDirectory' hides a field.241
     Error coding AvoidInlineConditionals Avoid inline conditionals.236
    243
     Error sizes LineLengthLine is longer than 80 characters (found 111).237
    Line is longer than 80 characters (found 107).244
     Error sizes LineLengthLine is longer than 80 characters (found 104).238
     ErrorsizesLineLengthLine is longer than 80 characters (found 85).239
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).243
     ErrorjavadocJavadocMethodMissing a Javadoc comment.243
     ErrormiscFinalParametersParameter config should be final.243
     ErrormiscFinalParametersParameter contractsDslDir should be final.243
     ErrorsizesLineLengthLine is longer than 80 characters (found 93).Line is longer than 80 characters (found 96). 245
     Error sizes LineLengthLine is longer than 80 characters (found 119).248
    Line is longer than 80 characters (found 92).246
     Error sizes250
     ErrorjavadocJavadocMethodMissing a Javadoc comment.250
     ErrormiscFinalParametersParameter config should be final.250
     ErrormiscFinalParametersParameter contractsDslDir should be final.250
     ErrorsizesLineLengthLine is longer than 80 characters (found 93).252
     ErrorsizesLineLengthLine is longer than 80 characters (found 119).255
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).257
     Error sizes LineLength Line is longer than 80 characters (found 87).252
    259
     Error javadoc JavadocMethod Missing a Javadoc comment.256
    263
     Error misc FinalParameters Parameter contractsDirectory should be final.256
    263
     Error coding HiddenField 'contractsDirectory' hides a field.256
    263
     Error sizes LineLength Line is longer than 80 characters (found 84).257
    264
     Error sizes LineLength Line is longer than 80 characters (found 123).261
    268
     Error sizes LineLength Line is longer than 80 characters (found 83).268
    275
     Error javadoc JavadocMethod Missing a Javadoc comment.268
    275
     Error misc FinalParameters Parameter config should be final.268
    275
     Error sizes LineLength Line is longer than 80 characters (found 90).269
    276
     Error sizes LineLength Line is longer than 80 characters (found 100).270
    277
     Error sizes LineLength Line is longer than 80 characters (found 100).272
    279
     Error sizes LineLength Line is longer than 80 characters (found 93).273
    280
     Error sizes LineLength Line is longer than 80 characters (found 102).274
    281
     Error javadoc JavadocMethod Missing a Javadoc comment.278
    285
     Error misc FinalParameters Parameter rootPath should be final.278
     ErrorwhitespaceOperatorWrap'?' should be on a new line.279
     ErrorcodingAvoidInlineConditionalsAvoid inline conditionals.279
    285
     Error sizes LineLengthLine is longer than 80 characters (found 107).280
    Line is longer than 80 characters (found 98).286
     ErrorjavadocJavadocMethodMissing a Javadoc comment.283
     ErrormiscFinalParametersParameter contractsDirectory should be final.283
     ErrorcodingHiddenField'contractsDirectory' hides a field.283
     Error coding AvoidInlineConditionals Avoid inline conditionals.284
    286
     Error javadoc JavadocMethod Missing a Javadoc comment.287
    +290 + + Error +misc +FinalParameters +Parameter contractsDirectory should be final. +290 + + Error +coding +HiddenField +'contractsDirectory' hides a field. +290 + + Error +coding +AvoidInlineConditionals +Avoid inline conditionals. +291 + + Error +javadoc +JavadocMethod +Missing a Javadoc comment. +294

    org/springframework/cloud/contract/maven/verifier/CopyContracts.java

    - + - + - - + + - - + + - - + + - - - - - - - + - + - + - + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - + + - - + + - + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - + -
    Severity Category Rule Message Line
     Error javadoc JavadocType Missing a Javadoc comment.32
    34
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).33
    36
     Error javadoc JavadocVariable Missing a Javadoc comment.33
    36
     Error naming ConstantName Name 'log' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.33
     ErrorjavadocJavadocVariableMissing a Javadoc comment.35
    36
     Error javadoc JavadocVariable Missing a Javadoc comment.37
    38
     Error javadoc JavadocVariable Missing a Javadoc comment.39
    40
     Error javadoc JavadocVariable Missing a Javadoc comment.41
    42
     Error javadocJavadocVariableMissing a Javadoc comment.44
     Errorjavadoc JavadocMethod Missing a Javadoc comment.43
    46
     Error misc FinalParameters Parameter project should be final.43
    46
     Error coding HiddenField 'project' hides a field.43
    46
     Error misc FinalParameters Parameter mavenSession should be final.43
    46
     Error coding HiddenField 'mavenSession' hides a field.43
    46
     Error misc FinalParameters Parameter mavenResourcesFiltering should be final.44
    47
     Error coding HiddenField 'mavenResourcesFiltering' hides a field.44
    47
     Error misc FinalParameters Parameter config should be final.45
    48
     Error coding HiddenField 'config' hides a field.45
    48
     Error javadoc JavadocMethod Missing a Javadoc comment.52
    55
     Error misc FinalParameters Parameter contractsDirectory should be final.52
    55
     Error misc FinalParameters Parameter outputDirectory should be final.52
     ErrorsizesLineLengthLine is longer than 80 characters (found 103).54
     ErrorwhitespaceWhitespaceAround'+' is not preceded with whitespace.54
     ErrorsizesLineLengthLine is longer than 80 characters (found 126). 55
     Error sizes LineLengthLine is longer than 80 characters (found 89).60
    Line is longer than 80 characters (found 98).57
     Error sizes LineLengthLine is longer than 80 characters (found 85).62
    Line is longer than 80 characters (found 102).58
     Error sizes LineLength Line is longer than 80 characters (found 93).66
    59
     Error sizes LineLengthLine is longer than 80 characters (found 89).63
     ErrorsizesLineLengthLine is longer than 80 characters (found 85).65
     ErrorsizesLineLengthLine is longer than 80 characters (found 93).69
     ErrorsizesLineLength Line is longer than 80 characters (found 82).77
    80
     Error blocks RightCurly '}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).89
    92
     Error sizes LineLength Line is longer than 80 characters (found 93).95
    98
     Error javadoc JavadocMethod Missing a Javadoc comment.95
    98
     Error misc FinalParameters Parameter includedRootFolderAntPattern should be final.95
    98
     Error sizes LineLength Line is longer than 80 characters (found 85).96
    99
     Error blocks RightCurly '}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).98
    101
     Error sizes LineLength Line is longer than 80 characters (found 88).99
    102
     Error sizes LineLength Line is longer than 80 characters (found 90).100
    103
     Error sizes LineLength Line is longer than 80 characters (found 91).106
    109
     Error javadoc JavadocMethod Missing a Javadoc comment.106
    109
     Error misc FinalParameters Parameter includedRootFolderAntPattern should be final.106
    109
     Error sizes LineLength Line is longer than 80 characters (found 83).107
    110
     Error blocks RightCurly '}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).109
    112
     Error sizes LineLength Line is longer than 80 characters (found 90).110
    113
     Error sizes LineLength Line is longer than 80 characters (found 92).111
     ErrorjavadocJavadocMethodMissing a Javadoc comment.117
    114
     Error javadoc JavadocMethod Missing a Javadoc comment.121
    +120 + + Error +javadoc +JavadocMethod +Missing a Javadoc comment. +124

    org/springframework/cloud/contract/maven/verifier/GenerateStubsMojo.java

    - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Severity Category Rule Message Line
     Error sizes LineLength Line is longer than 80 characters (found 85).36
    37
     Error sizes LineLength Line is longer than 80 characters (found 92).39
    42
     Error sizes LineLength Line is longer than 80 characters (found 97).42
    45
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).42
    45
     Error javadoc JavadocVariable Missing a Javadoc comment.42
    45
     Error sizes LineLength Line is longer than 80 characters (found 98).45
    48
     Error javadoc JavadocVariable Missing a Javadoc comment.45
     ErrorjavadocJavadocStyleFirst sentence should end with a period. 48
     Error sizes LineLength Line is longer than 80 characters (found 92).51
     ErrorjavadocJavadocStyleFirst sentence should end with a period. 54
     Error sizes LineLength Line is longer than 80 characters (found 96).57
    60
     ErrorjavadocJavadocVariableMissing a Javadoc comment.63
     Error javadoc JavadocVariable Missing a Javadoc comment.72
     ErrorjavadocJavadocVariableMissing a Javadoc comment.75
     ErrorjavadocJavadocVariableMissing a Javadoc comment.78
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).81
     ErrordesignDesignForExtensionClass 'GenerateStubsMojo' looks like designed for extension (can be subclassed), but the method 'execute' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateStubsMojo' final or making the method 'execute' static/final/abstract/empty, or adding allowed annotation for the method.81
     ErrorjavadocJavadocMethodMissing a Javadoc comment.81
     ErrorsizesLineLengthLine is longer than 80 characters (found 129).84
     ErrorsizesLineLengthLine is longer than 80 characters (found 114).85
     ErrorsizesLineLengthLine is longer than 80 characters (found 87).90
     ErrorjavadocJavadocMethodMissing a Javadoc comment.94
     ErrormiscFinalParametersParameter stubsOutputDir should be final.94
     ErrorsizesLineLengthLine is longer than 80 characters (found 86).97
     ErrorsizesLineLengthLine is longer than 80 characters (found 114).99
     ErrorsizesLineLengthLine is longer than 80 characters (found 85).101
     ErrorsizesLineLengthLine is longer than 80 characters (found 90).103
     ErrorsizesLineLengthLine is longer than 80 characters (found 82).105
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).106
     ErrorsizesLineLengthLine is longer than 80 characters (found 93).108
     ErrorwhitespaceNoWhitespaceAfter'{' is followed by whitespace.108
     ErrorsizesLineLengthLine is longer than 80 characters (found 99).109
     ErrorcodingAvoidInlineConditionalsAvoid inline conditionals.109
     ErrorsizesLineLengthLine is longer than 80 characters (found 109).113
     ErrorblocksRightCurly'}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).115
     ErrorsizesLineLengthLine is longer than 80 characters (found 101).118
     ErrorjavadocJavadocMethodMissing a Javadoc comment.123
     ErrorjavadocJavadocMethodMissing a Javadoc comment.133
     ErrorsizesLineLengthLine is longer than 80 characters (found 84).134
    +
    +

    org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1744,853 +1860,526 @@ - - - - - - - - - - - - - + - - - + + + - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - -
    SeverityCategoryRuleMessageLine
     ErrorjavadocJavadocPackageMissing package-info.java file.
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).47
     ErrorsizesLineLengthLine is longer than 80 characters (found 135).52
     ErrorwhitespaceFileTabCharacterFile contains tab characters (this is the first instance).55
     ErrorjavadocJavadocVariableMissing a Javadoc comment.55
     ErrorjavadocJavadocVariableMissing a Javadoc comment.57
     ErrorsizesLineLengthLine is longer than 80 characters (found 148). 60
     Error javadocJavadocStyleFirst sentence should end with a period.JavadocVariableMissing a Javadoc comment.60
     ErrorsizesLineLengthLine is longer than 80 characters (found 96). 63
     ErrorjavadocJavadocVariableMissing a Javadoc comment.63
     ErrorsizesLineLengthLine is longer than 80 characters (found 98).66
     ErrorjavadocJavadocVariableMissing a Javadoc comment.66
     Error javadoc75
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).78
     ErrordesignDesignForExtensionClass 'GenerateStubsMojo' looks like designed for extension (can be subclassed), but the method 'execute' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateStubsMojo' final or making the method 'execute' static/final/abstract/empty, or adding allowed annotation for the method.78
     Error javadocJavadocMethodJavadocVariable Missing a Javadoc comment. 78
     ErrorsizesLineLengthLine is longer than 80 characters (found 129).javadocJavadocVariableMissing a Javadoc comment. 81
     ErrorsizesLineLengthLine is longer than 80 characters (found 114).82
     ErrorsizesLineLengthLine is longer than 80 characters (found 87).87
     Error javadocJavadocMethodJavadocVariable Missing a Javadoc comment.91
    84
     ErrormiscFinalParametersParameter stubsOutputDir should be final.91
     Error sizes LineLength Line is longer than 80 characters (found 86).94
     ErrorsizesLineLengthLine is longer than 80 characters (found 114).96
     ErrorsizesLineLengthLine is longer than 80 characters (found 85).98
     ErrorsizesLineLengthLine is longer than 80 characters (found 90).100
     ErrorsizesLineLengthLine is longer than 80 characters (found 82).102
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).103
     ErrorsizesLineLengthLine is longer than 80 characters (found 93).105
     ErrorwhitespaceNoWhitespaceAfter'{' is followed by whitespace.105
     ErrorsizesLineLengthLine is longer than 80 characters (found 99).106
     ErrorcodingAvoidInlineConditionalsAvoid inline conditionals.106
     ErrorsizesLineLengthLine is longer than 80 characters (found 109).110
     ErrorblocksRightCurly'}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally). 112
     Error sizes LineLengthLine is longer than 80 characters (found 101).Line is longer than 80 characters (found 99). 115
     ErrorjavadocJavadocMethodMissing a Javadoc comment.120
     ErrorjavadocJavadocMethodMissing a Javadoc comment.130
     ErrorsizesLineLengthLine is longer than 80 characters (found 84).131
    -
    -

    org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + - + + + + + + + - - + + - - + + - - + + - + + + + + + + - + - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - + + - + - + - - - + + + - - - - + + + + - - - - + + + + - + - - - - - - - - + + - - - - - - - + - + - - - - - - - - - - - - - - + + - + - + - + - + - + - + - + - - - - - - - - - - - - - + - + - + - - - + + + - - + + - - + + - + - - + + - - - - - - + + + + + + - + - + - + - + - - + + - + - + - + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + -
    SeverityCategoryRuleMessageLine
     ErrorjavadocJavadocPackageMissing package-info.java file.
     ErrorjavadocJavadocStyleFirst sentence should end with a period.45
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).46
     ErrorsizesLineLengthLine is longer than 80 characters (found 135).49
     ErrorwhitespaceFileTabCharacterFile contains tab characters (this is the first instance).52
     ErrorjavadocJavadocVariableMissing a Javadoc comment.52
     ErrorsizesLineLengthLine is longer than 80 characters (found 148).55
     ErrorjavadocJavadocVariableMissing a Javadoc comment.55
     ErrorsizesLineLengthLine is longer than 80 characters (found 96).58
     ErrorjavadocJavadocVariableMissing a Javadoc comment.58
     ErrorsizesLineLengthLine is longer than 80 characters (found 98).61
     ErrorjavadocJavadocVariableMissing a Javadoc comment.61
     ErrorjavadocJavadocVariableMissing a Javadoc comment.64
     ErrorjavadocJavadocVariableMissing a Javadoc comment.67
     ErrorjavadocJavadocVariableMissing a Javadoc comment.70
     ErrorjavadocJavadocVariableMissing a Javadoc comment.73
     ErrorjavadocJavadocVariableMissing a Javadoc comment.76
     ErrorjavadocJavadocVariableMissing a Javadoc comment.79
     ErrorjavadocJavadocStyleFirst sentence should end with a period.82
     ErrorjavadocJavadocStyleFirst sentence should end with a period.88
     ErrorjavadocJavadocStyleFirst sentence should end with a period.94
     ErrorjavadocJavadocStyleFirst sentence should end with a period.100
     ErrorsizesLineLengthLine is longer than 80 characters (found 86).107
     ErrorsizesLineLengthLine is longer than 80 characters (found 99).110
     ErrorjavadocJavadocStyleFirst sentence should end with a period.113
     ErrorsizesLineLengthLine is longer than 80 characters (found 91).114
     ErrorjavadocJavadocVariableMissing a Javadoc comment.119
     Error sizes LineLength Line is longer than 80 characters (found 92).122
     ErrorjavadocJavadocVariableMissing a Javadoc comment.122
    119
     Error javadoc JavadocVariable Missing a Javadoc comment.125
    124
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).127
     ErrorjavadocJavadocVariableMissing a Javadoc comment.127
     Error javadoc JavadocVariable Missing a Javadoc comment.128
    130
     ErrorjavadocJavadocVariableMissing a Javadoc comment.133
     Error sizes LineLength Line is longer than 80 characters (found 84).132
    137
     Error sizes LineLength Line is longer than 80 characters (found 88).133
    138
     Error javadoc JavadocVariable Missing a Javadoc comment.139
    144
     Error sizes LineLength Line is longer than 80 characters (found 89).143
    148
     ErrorsizesLineLengthLine is longer than 80 characters (found 87).149
     Error sizes LineLength Line is longer than 80 characters (found 87).144
    150
     ErrorjavadocJavadocStyleExtra HTML tag found: </p>146
     Error sizes LineLengthLine is longer than 80 characters (found 94).147
     ErrorjavadocJavadocStyleFirst sentence should end with a period.153
    Line is longer than 80 characters (found 89).151
     Error sizes LineLength Line is longer than 80 characters (found 92).160
     ErrorsizesLineLengthLine is longer than 80 characters (found 93).161
     ErrorsizesLineLengthLine is longer than 80 characters (found 93). 163
     Error sizes LineLengthLine is longer than 80 characters (found 89).165
    Line is longer than 80 characters (found 93).164
     Error sizes LineLength Line is longer than 80 characters (found 93).172
    166
     Error sizes LineLength Line is longer than 80 characters (found 89).173
    168
     ErrorjavadocJavadocStyleExtra HTML tag found: </p>sizesLineLengthLine is longer than 80 characters (found 93). 175
     ErrorjavadocJavadocStyleExtra HTML tag found: </p>177
    sizesLineLengthLine is longer than 80 characters (found 89).176
     ErrorjavadocJavadocStyleExtra HTML tag found: </p>179
    sizesLineLengthLine is longer than 80 characters (found 91).178
     Error sizes LineLength Line is longer than 80 characters (found 91).180
    179
     ErrorjavadocJavadocStyleFirst sentence should end with a period.211
     Error sizes LineLength Line is longer than 80 characters (found 92).212
    210
     Error sizes LineLength Line is longer than 80 characters (found 83).216
     ErrorjavadocJavadocStyleFirst sentence should end with a period.220
    214
     Error sizes LineLength Line is longer than 80 characters (found 94).221
    219
     ErrorjavadocJavadocStyleFirst sentence should end with a period.227
     Error sizes LineLengthLine is longer than 80 characters (found 86).229
     ErrorjavadocJavadocVariableMissing a Javadoc comment.234
    Line is longer than 80 characters (found 87).227
     Error javadoc JavadocMethod Missing a Javadoc comment.236
    232
     Error sizes LineLength Line is longer than 80 characters (found 91).237
    233
     Error misc FinalParameters Parameter aetherStubDownloaderFactory should be final.237
    233
     Error coding HiddenField 'aetherStubDownloaderFactory' hides a field.237
    233
     Error sizes LineLength Line is longer than 80 characters (found 83).241
    237
     Error design DesignForExtension Class 'GenerateTestsMojo' looks like designed for extension (can be subclassed), but the method 'execute' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateTestsMojo' final or making the method 'execute' static/final/abstract/empty, or adding allowed annotation for the method.241
    237
     Error javadoc JavadocMethod Missing a Javadoc comment.241
    237
     ErrorblocksNeedBraces'if' construct must use '{}'s.243
     Error sizes LineLength Line is longer than 80 characters (found 137).245
     ErrorblocksNeedBraces'if' construct must use '{}'s.247
    241
     Error sizes LineLength Line is longer than 80 characters (found 117).249
    246
     Error sizes LineLength Line is longer than 80 characters (found 86).250
    247
     ErrorblocksNeedBraces'if' construct must use '{}'s.sizesLineLengthLine is longer than 80 characters (found 110). 251
     Error sizes LineLengthLine is longer than 80 characters (found 110).253
    Line is longer than 80 characters (found 82).252
     Error sizes LineLengthLine is longer than 80 characters (found 82).254
    Line is longer than 80 characters (found 128).257
     Error sizes LineLengthLine is longer than 80 characters (found 128).Line is longer than 80 characters (found 103). 258
     Error sizes LineLengthLine is longer than 80 characters (found 103).259
    Line is longer than 80 characters (found 84).260
     ErrorsizesLineLengthLine is longer than 80 characters (found 109).261
     Error coding HiddenField 'contractsDirectory' hides a field.260
     ErrorsizesLineLengthLine is longer than 80 characters (found 105). 261
     Error sizes LineLengthLine is longer than 80 characters (found 110).Line is longer than 80 characters (found 95). 262
     Error sizes LineLengthLine is longer than 80 characters (found 99).Line is longer than 80 characters (found 100). 263
     Error sizes LineLengthLine is longer than 80 characters (found 101).Line is longer than 80 characters (found 93). 264
     Error sizes LineLengthLine is longer than 80 characters (found 155).Line is longer than 80 characters (found 102). 265
     Error sizes LineLengthLine is longer than 80 characters (found 100).266
    Line is longer than 80 characters (found 102).268
     Error sizes LineLength Line is longer than 80 characters (found 106).269
    271
     Error sizes LineLength Line is longer than 80 characters (found 88).271
    273
     Error sizes LineLength Line is longer than 80 characters (found 102).276
    277
     Error sizes LineLength Line is longer than 80 characters (found 88).279
     ErrorsizesLineLengthLine is longer than 80 characters (found 101). 280
     Error sizes LineLength Line is longer than 80 characters (found 101). 281
     ErrorsizesLineLengthLine is longer than 80 characters (found 101).282
     Error sizes LineLength Line is longer than 80 characters (found 90).287
    288
     Error blocks RightCurly '}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).288
    289
     Error sizes LineLength Line is longer than 80 characters (found 108).291
    292
     Error javadoc JavadocMethod Missing a Javadoc comment.297
    298
     Error misc FinalParameters Parameter config should be final.297
    298
     Error misc FinalParameters Parameter contractsDirectory should be final.298
    299
     Error coding HiddenField 'contractsDirectory' hides a field.298
    299
     Error sizes LineLength Line is longer than 80 characters (found 84).301
    302
     Error design DesignForExtension Class 'GenerateTestsMojo' looks like designed for extension (can be subclassed), but the method 'mappingsToMap' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateTestsMojo' final or making the method 'mappingsToMap' static/final/abstract/empty, or adding allowed annotation for the method.320
    321
     Error javadoc JavadocMethod Missing a Javadoc comment.320
    321
     Error sizes LineLength Line is longer than 80 characters (found 94).326
    327
     Error design DesignForExtension Class 'GenerateTestsMojo' looks like designed for extension (can be subclassed), but the method 'getExcludedFiles' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateTestsMojo' final or making the method 'getExcludedFiles' static/final/abstract/empty, or adding allowed annotation for the method.331
    332
     Error javadoc JavadocMethod Missing a Javadoc comment.331
    332
     Error design DesignForExtension Class 'GenerateTestsMojo' looks like designed for extension (can be subclassed), but the method 'setExcludedFiles' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateTestsMojo' final or making the method 'setExcludedFiles' static/final/abstract/empty, or adding allowed annotation for the method.335
    336
     Error javadoc JavadocMethod Missing a Javadoc comment.335
    336
     Error misc FinalParameters Parameter excludedFiles should be final.335
    336
     Error coding HiddenField 'excludedFiles' hides a field.335
    336
     Error design DesignForExtension Class 'GenerateTestsMojo' looks like designed for extension (can be subclassed), but the method 'getIgnoredFiles' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateTestsMojo' final or making the method 'getIgnoredFiles' static/final/abstract/empty, or adding allowed annotation for the method.339
    340
     Error javadoc JavadocMethod Missing a Javadoc comment.339
    340
     Error design DesignForExtension Class 'GenerateTestsMojo' looks like designed for extension (can be subclassed), but the method 'setIgnoredFiles' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateTestsMojo' final or making the method 'setIgnoredFiles' static/final/abstract/empty, or adding allowed annotation for the method.343
    344
     Error javadoc JavadocMethod Missing a Javadoc comment.343
    344
     Error misc FinalParameters Parameter ignoredFiles should be final.343
    344
     Error coding HiddenField 'ignoredFiles' hides a field.343
    344
     Error design DesignForExtension Class 'GenerateTestsMojo' looks like designed for extension (can be subclassed), but the method 'isAssertJsonSize' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateTestsMojo' final or making the method 'isAssertJsonSize' static/final/abstract/empty, or adding allowed annotation for the method.347
    348
     Error javadoc JavadocMethod Missing a Javadoc comment.347
    348
     Error design DesignForExtension Class 'GenerateTestsMojo' looks like designed for extension (can be subclassed), but the method 'setAssertJsonSize' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'GenerateTestsMojo' final or making the method 'setAssertJsonSize' static/final/abstract/empty, or adding allowed annotation for the method.351
    352
     Error javadoc JavadocMethod Missing a Javadoc comment.351
    352
     Error misc FinalParameters Parameter assertJsonSize should be final.351
    352
     Error coding HiddenField 'assertJsonSize' hides a field.351
    +352

    org/springframework/cloud/contract/maven/verifier/ManifestCreator.java

    @@ -2605,628 +2394,628 @@ - - - - - - - - - - - - - + - + - + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - + - - + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + -
    javadoc JavadocType Missing a Javadoc comment.26
     ErrordesignHideUtilityClassConstructorUtility classes should not have a public or default constructor.26
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).28
    27
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).28
    29
     Error javadoc JavadocMethod Missing a Javadoc comment.28
    29
     ErrorsizesLineLengthLine is longer than 80 characters (found 85).30
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).33
     ErrorjavadocJavadocMethodMissing a Javadoc comment.33
     Error misc FinalParameters Parameter project should be final.28
    33
     Error sizes LineLength Line is longer than 80 characters (found 88).30
     ErrorsizesLineLengthLine is longer than 80 characters (found 108).33
    35
     Error sizes LineLengthLine is longer than 80 characters (found 91).34
    Line is longer than 80 characters (found 108).38
     Error sizes LineLengthLine is longer than 80 characters (found 91).39
     ErrorsizesLineLength Line is longer than 80 characters (found 86).37
    42
     Error sizes LineLength Line is longer than 80 characters (found 89).41
    46
     Error sizes LineLength Line is longer than 80 characters (found 87).42
    47
     Error sizes LineLength Line is longer than 80 characters (found 108).43
    48
     Error javadoc JavadocMethod Missing a Javadoc comment.49
    54
     Error misc FinalParameters Parameter plugins should be final.49
    54
     Error sizes LineLength Line is longer than 80 characters (found 98).51
    56
     Error sizes LineLength Line is longer than 80 characters (found 81).58
    63
     Error javadoc JavadocMethod Missing a Javadoc comment.58
    63
     Error misc FinalParameters Parameter deps should be final.58
    63
     Error sizes LineLength Line is longer than 80 characters (found 91).60
    +65

    org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java

    - + - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - + - + - + - + - + - + - + - + -
    Severity Category Rule Message Line
     ErrorjavadocJavadocStyleFirst sentence should end with a period.35
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).43
    44
     Error javadoc JavadocVariable Missing a Javadoc comment.43
    44
     Error sizes LineLength Line is longer than 80 characters (found 85).45
    46
     Error javadoc JavadocVariable Missing a Javadoc comment.45
    46
     Error javadoc JavadocVariable Missing a Javadoc comment.47
    48
     Error javadoc JavadocVariable Missing a Javadoc comment.49
    50
     Error javadoc JavadocVariable Missing a Javadoc comment.51
    52
     Error javadoc JavadocVariable Missing a Javadoc comment.53
    54
     Error javadoc JavadocVariable Missing a Javadoc comment.55
    56
     Error javadoc JavadocVariable Missing a Javadoc comment.57
    58
     Error sizes LineLength Line is longer than 80 characters (found 82).59
    60
     Error javadoc JavadocVariable Missing a Javadoc comment.59
    60
     Error javadoc JavadocVariable Missing a Javadoc comment.61
    62
     Error javadoc JavadocVariable Missing a Javadoc comment.63
    64
     Error javadoc JavadocVariable Missing a Javadoc comment.65
    66
     Error javadoc JavadocVariable Missing a Javadoc comment.67
    68
     Error javadoc JavadocVariable Missing a Javadoc comment.69
    70
     Error javadoc JavadocVariable Missing a Javadoc comment.71
    72
     Error sizes LineLength Line is longer than 80 characters (found 85).73
    74
     Error javadoc JavadocMethod Missing a Javadoc comment.73
    74
     Error sizes ParameterNumber More than 7 parameters (found 12).73
    74
     Error misc FinalParameters Parameter project should be final.73
    74
     Error coding HiddenField 'project' hides a field.73
    74
     Error misc FinalParameters Parameter contractDependency should be final.73
    74
     Error coding HiddenField 'contractDependency' hides a field.73
    74
     Error misc FinalParameters Parameter contractsPath should be final.74
    75
     Error coding HiddenField 'contractsPath' hides a field.74
    75
     Error misc FinalParameters Parameter contractsRepositoryUrl should be final.74
    75
     Error coding HiddenField 'contractsRepositoryUrl' hides a field.74
    75
     Error sizes LineLength Line is longer than 80 characters (found 101).75
    76
     Error misc FinalParameters Parameter stubsMode should be final.75
    76
     Error coding HiddenField 'stubsMode' hides a field.75
    76
     Error misc FinalParameters Parameter log should be final.75
    76
     Error coding HiddenField 'log' hides a field.75
    76
     Error misc FinalParameters Parameter repositoryUsername should be final.75
    76
     Error coding HiddenField 'repositoryUsername' hides a field.75
    76
     Error misc FinalParameters Parameter repositoryPassword should be final.76
    77
     Error coding HiddenField 'repositoryPassword' hides a field.76
    77
     Error misc FinalParameters Parameter repositoryProxyHost should be final.76
    77
     Error coding HiddenField 'repositoryProxyHost' hides a field.76
    77
     Error sizes LineLength Line is longer than 80 characters (found 82).77
    78
     Error misc FinalParameters Parameter repositoryProxyPort should be final.77
    78
     Error coding HiddenField 'repositoryProxyPort' hides a field.77
    78
     Error misc FinalParameters Parameter deleteStubsAfterTest should be final.77
    78
     Error coding HiddenField 'deleteStubsAfterTest' hides a field.77
    78
     Error misc FinalParameters Parameter contractsProperties should be final.78
    79
     Error coding HiddenField 'contractsProperties' hides a field.78
    79
     Error sizes LineLength Line is longer than 80 characters (found 89).89
    90
     Error sizes LineLength Line is longer than 80 characters (found 90).94
    95
     Error javadoc JavadocMethod Missing a Javadoc comment.94
    95
     Error misc FinalParameters Parameter config should be final.94
    95
     Error misc FinalParameters Parameter defaultContractsDir should be final.95
    96
     Error sizes LineLength Line is longer than 80 characters (found 87).98
    99
     Error coding AvoidInlineConditionals Avoid inline conditionals.99
    100
     Error sizes LineLength Line is longer than 80 characters (found 88).101
    102
     Error sizes LineLength Line is longer than 80 characters (found 108).103
    104
     Error sizes LineLength Line is longer than 80 characters (found 88).104
    105
     Error sizes LineLength Line is longer than 80 characters (found 98).105
    106
     Error blocks RightCurly '}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).108
    109
     Error sizes LineLength Line is longer than 80 characters (found 124).111
    112
     Error sizes LineLength Line is longer than 80 characters (found 90).114
    115
     Error sizes LineLength Line is longer than 80 characters (found 97).118
    119
     Error javadoc JavadocMethod Missing a Javadoc comment.123
    124
     Error sizes LineLength Line is longer than 80 characters (found 95).125
    126
     Error sizes LineLength Line is longer than 80 characters (found 84).126
    127
     Error javadoc JavadocMethod Missing a Javadoc comment.129
    130
     Error sizes LineLength Line is longer than 80 characters (found 84).130
    131
     Error sizes LineLength Line is longer than 80 characters (found 89).132
    133
     Error javadoc JavadocMethod Missing a Javadoc comment.135
    136
     Error sizes LineLength Line is longer than 80 characters (found 81).137
    138
     Error javadoc JavadocMethod Missing a Javadoc comment.140
     ErrorsizesLineLengthLine is longer than 80 characters (found 81). 141
     Error sizes LineLength Line is longer than 80 characters (found 81). 142
     ErrorsizesLineLengthLine is longer than 80 characters (found 81).143
     Error sizes LineLength Line is longer than 80 characters (found 100).143
    144
     Error sizes LineLength Line is longer than 80 characters (found 84).145
    146
     Error sizes LineLength Line is longer than 80 characters (found 84).148
    149
     Error sizes LineLength Line is longer than 80 characters (found 94).151
    152
     Error javadoc JavadocMethod Missing a Javadoc comment.156
    157
     Error sizes LineLength Line is longer than 80 characters (found 90).159
    160
     Error sizes LineLength Line is longer than 80 characters (found 88).160
    161
     Error coding AvoidInlineConditionals Avoid inline conditionals.160
    161
     Error sizes LineLength Line is longer than 80 characters (found 87).162
    +163

    org/springframework/cloud/contract/maven/verifier/PushStubsToScmMojo.java

    @@ -3241,199 +3030,175 @@ - + - + - + - + - + - - - - - - - - - - - - - + - + - + - + - - - - - - - - - - - - - + - + - - - - - - - - - + + + - - + + - - - - - - - + - - + + - + - - + + - - + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + -
    sizes LineLength Line is longer than 80 characters (found 97).40
    44
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).40
    44
     Error javadoc JavadocVariable Missing a Javadoc comment.40
    44
     Error sizes LineLength Line is longer than 80 characters (found 98).43
    47
     Error javadoc JavadocVariable Missing a Javadoc comment.43
    47
     ErrorjavadocJavadocStyleFirst sentence should end with a period.46
     Error sizes LineLength Line is longer than 80 characters (found 92).49
     ErrorjavadocJavadocStyleFirst sentence should end with a period.52
    53
     Error sizes LineLength Line is longer than 80 characters (found 113).55
    59
     Error javadoc JavadocVariable Missing a Javadoc comment.58
    62
     Error sizes LineLength Line is longer than 80 characters (found 84).74
    78
     Error sizes LineLength Line is longer than 80 characters (found 88).75
     ErrorjavadocJavadocStyleFirst sentence should end with a period.81
     ErrorjavadocJavadocStyleFirst sentence should end with a period.87
    79
     Error sizes LineLength Line is longer than 80 characters (found 94).88
    92
     ErrorjavadocJavadocStyleFirst sentence should end with a period.94
     Error sizes LineLengthLine is longer than 80 characters (found 86).96
    Line is longer than 80 characters (found 87).100
     Error design DesignForExtension Class 'PushStubsToScmMojo' looks like designed for extension (can be subclassed), but the method 'execute' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'PushStubsToScmMojo' final or making the method 'execute' static/final/abstract/empty, or adding allowed annotation for the method.101
    105
     Error javadoc JavadocMethod Missing a Javadoc comment.101
     ErrorsizesLineLengthLine is longer than 80 characters (found 129).104
    105
     Error sizes LineLengthLine is longer than 80 characters (found 119).106
    Line is longer than 80 characters (found 129).108
     Error sizes LineLengthLine is longer than 80 characters (found 97).Line is longer than 80 characters (found 119). 110
     Error sizes LineLengthLine is longer than 80 characters (found 83).111
    Line is longer than 80 characters (found 97).114
     Error sizes LineLengthLine is longer than 80 characters (found 162).113
    Line is longer than 80 characters (found 83).115
     ErrorsizesLineLengthLine is longer than 80 characters (found 81).116
     ErrorsizesLineLengthLine is longer than 80 characters (found 123).117
     Error sizes LineLength Line is longer than 80 characters (found 97).117
    121
     Error sizes LineLength Line is longer than 80 characters (found 88).118
    122
     Error sizes LineLength Line is longer than 80 characters (found 93).119
    123
     Error design DesignForExtension Class 'PushStubsToScmMojo' looks like designed for extension (can be subclassed), but the method 'buildOptions' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'PushStubsToScmMojo' final or making the method 'buildOptions' static/final/abstract/empty, or adding allowed annotation for the method.123
    127
     Error javadoc JavadocMethod Missing a Javadoc comment.123
    127
     Error sizes LineLength Line is longer than 80 characters (found 81).124
    128
     Error sizes LineLength Line is longer than 80 characters (found 81).125
    129
     Error sizes LineLength Line is longer than 80 characters (found 84).126
    130
     Error sizes LineLength Line is longer than 80 characters (found 84).130
    +134

    org/springframework/cloud/contract/maven/verifier/RunMojo.java

    @@ -3448,19 +3213,286 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    sizes LineLength Line is longer than 80 characters (found 100).43
    48
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).46
    51
     Error javadoc JavadocVariable Missing a Javadoc comment.46
    51
     ErrorjavadocJavadocVariableMissing a Javadoc comment.53
     ErrorjavadocJavadocVariableMissing a Javadoc comment.55
     ErrorjavadocJavadocVariableMissing a Javadoc comment.58
     ErrorjavadocJavadocVariableMissing a Javadoc comment.61
     ErrorsizesLineLengthLine is longer than 80 characters (found 96).67
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).73
     ErrorsizesLineLengthLine is longer than 80 characters (found 100).79
     ErrorsizesLineLengthLine is longer than 80 characters (found 84).83
     ErrorsizesLineLengthLine is longer than 80 characters (found 100).91
     ErrorsizesLineLengthLine is longer than 80 characters (found 100).97
     ErrorsizesLineLengthLine is longer than 80 characters (found 89).101
     ErrorsizesLineLengthLine is longer than 80 characters (found 107).103
     ErrorjavadocJavadocVariableMissing a Javadoc comment.112
     ErrorjavadocJavadocMethodMissing a Javadoc comment.115
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).116
     ErrormiscFinalParametersParameter localStubRunner should be final.116
     ErrorcodingHiddenField'localStubRunner' hides a field.116
     ErrormiscFinalParametersParameter remoteStubRunner should be final.116
     ErrorcodingHiddenField'remoteStubRunner' hides a field.116
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).121
     ErrordesignDesignForExtensionClass 'RunMojo' looks like designed for extension (can be subclassed), but the method 'execute' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'RunMojo' final or making the method 'execute' static/final/abstract/empty, or adding allowed annotation for the method.121
     ErrorjavadocJavadocMethodMissing a Javadoc comment.121
     ErrorsizesLineLengthLine is longer than 80 characters (found 107).124
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).129
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).133
     ErrorsizesLineLengthLine is longer than 80 characters (found 97).135
     ErrorsizesLineLengthLine is longer than 80 characters (found 97).136
     ErrorblocksRightCurly'}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).137
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).139
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).140
     ErrorsizesLineLengthLine is longer than 80 characters (found 95).141
     ErrorblocksRightCurly'}' at column 4 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).147
     ErrorsizesLineLengthLine is longer than 80 characters (found 103).149
     ErrorjavadocJavadocMethodMissing a Javadoc comment.154
     ErrorblocksRightCurly'}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).157
     ErrorjavadocJavadocMethodMissing a Javadoc comment.163
     ErrorblocksRightCurly'}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).170
     ErrorjavadocJavadocMethodMissing a Javadoc comment.175
    +
    +

    org/springframework/cloud/contract/maven/verifier/stubrunner/AetherStubDownloaderFactory.java

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3470,408 +3502,105 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    SeverityCategoryRuleMessageLine
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).45
     ErrorwhitespaceFileTabCharacterFile contains tab characters (this is the first instance).45
     ErrorjavadocJavadocVariableMissing a Javadoc comment.45
     ErrornamingConstantNameName 'log' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.45
     ErrorjavadocJavadocVariableMissing a Javadoc comment.47
     Error javadoc
     Error javadocJavadocVariableMissing a Javadoc comment.52
     ErrorjavadocJavadocStyleFirst sentence should end with a period.55
     ErrorsizesLineLengthLine is longer than 80 characters (found 96).58
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).64
     ErrorsizesLineLengthLine is longer than 80 characters (found 100).70
     ErrorjavadocJavadocStyleFirst sentence should end with a period.73
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).74
     ErrorjavadocJavadocStyleFirst sentence should end with a period.79
     ErrorsizesLineLengthLine is longer than 80 characters (found 100).82
     ErrorjavadocJavadocStyleFirst sentence should end with a period.85
     ErrorsizesLineLengthLine is longer than 80 characters (found 100).88
     ErrorjavadocJavadocStyleFirst sentence should end with a period.91
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).92
     ErrorsizesLineLengthLine is longer than 80 characters (found 107).94
     ErrorjavadocJavadocVariableMissing a Javadoc comment.103
     ErrorjavadocJavadocVariableMissing a Javadoc comment.106
     ErrorjavadocJavadocVariableMissing a Javadoc comment.108
     Errorjavadoc JavadocMethod Missing a Javadoc comment.110
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).111
     ErrormiscFinalParametersParameter localStubRunner should be final.111
     ErrorcodingHiddenField'localStubRunner' hides a field.111
     ErrormiscFinalParametersParameter remoteStubRunner should be final.111
     ErrorcodingHiddenField'remoteStubRunner' hides a field.111
     ErrorsizesLineLengthLine is longer than 80 characters (found 83).116
     ErrordesignDesignForExtensionClass 'RunMojo' looks like designed for extension (can be subclassed), but the method 'execute' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'RunMojo' final or making the method 'execute' static/final/abstract/empty, or adding allowed annotation for the method.116
     ErrorjavadocJavadocMethodMissing a Javadoc comment.116
     ErrorsizesLineLengthLine is longer than 80 characters (found 107).119
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).124
     ErrorsizesLineLengthLine is longer than 80 characters (found 94).128
     ErrorsizesLineLengthLine is longer than 80 characters (found 97).130
     ErrorsizesLineLengthLine is longer than 80 characters (found 97).131
     ErrorblocksRightCurly'}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).132
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).134
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).135
     ErrorsizesLineLengthLine is longer than 80 characters (found 95).136
     ErrorblocksRightCurly'}' at column 4 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).142
     ErrorsizesLineLengthLine is longer than 80 characters (found 103).144
     ErrorjavadocJavadocMethodMissing a Javadoc comment.149
     ErrorblocksRightCurly'}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).152
     ErrorjavadocJavadocMethodMissing a Javadoc comment.158
     ErrorblocksRightCurly'}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).165
     ErrorjavadocJavadocMethodMissing a Javadoc comment.170
    -
    -

    org/springframework/cloud/contract/maven/verifier/stubrunner/AetherStubDownloaderFactory.java

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + -
    SeverityCategoryRuleMessageLine
     ErrorjavadocJavadocTypeMissing a Javadoc comment.34
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).38
     ErrorwhitespaceFileTabCharacterFile contains tab characters (this is the first instance).38
     ErrorjavadocJavadocVariableMissing a Javadoc comment.38
     ErrornamingConstantNameName 'log' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.38
     ErrorjavadocJavadocVariableMissing a Javadoc comment.40
     ErrorjavadocJavadocVariableMissing a Javadoc comment.42
     ErrorjavadocJavadocMethodMissing a Javadoc comment.44
    51
     Error misc FinalParameters Parameter repoSystem should be final.45
    52
     Error coding HiddenField 'repoSystem' hides a field.45
    52
     Error misc FinalParameters Parameter project should be final.46
    53
     Error coding HiddenField 'project' hides a field.46
    53
     Error sizes LineLength Line is longer than 80 characters (found 87).51
    58
     Error design DesignForExtension Class 'AetherStubDownloaderFactory' looks like designed for extension (can be subclassed), but the method 'build' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'AetherStubDownloaderFactory' final or making the method 'build' static/final/abstract/empty, or adding allowed annotation for the method.51
    58
     Error javadoc JavadocMethod Missing a Javadoc comment.51
     ErrorsizesLineLengthLine is longer than 80 characters (found 90).54
     ErrormiscFinalParametersParameter stubRunnerOptions should be final.54
     ErrorsizesLineLengthLine is longer than 80 characters (found 120).56
     ErrorsizesLineLengthLine is longer than 80 characters (found 92). 58
     Error sizes LineLengthLine is longer than 80 characters (found 90).61
     ErrormiscFinalParametersParameter stubRunnerOptions should be final.61
     ErrorsizesLineLengthLine is longer than 80 characters (found 120).63
     ErrorsizesLineLengthLine is longer than 80 characters (found 92).65
     ErrorsizesLineLength Line is longer than 80 characters (found 88).59
    66
     Error sizes LineLength Line is longer than 80 characters (found 96).60
    67
     Error sizes LineLength Line is longer than 80 characters (found 97).65
    72
     Error misc FinalParameters Parameter location should be final.65
    72
     Error misc FinalParameters Parameter resourceLoader should be final.65
    +72

    org/springframework/cloud/contract/maven/verifier/stubrunner/LocalStubRunner.java

    @@ -3889,181 +3618,169 @@ - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + -
     ErrorjavadocJavadocTypeMissing a Javadoc comment.26
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).29
    36
     Error javadoc JavadocVariable Missing a Javadoc comment.29
    36
     Error naming ConstantName Name 'log' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.29
    36
     Error sizes LineLength Line is longer than 80 characters (found 85).31
    38
     Error design DesignForExtension Class 'LocalStubRunner' looks like designed for extension (can be subclassed), but the method 'run' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'LocalStubRunner' final or making the method 'run' static/final/abstract/empty, or adding allowed annotation for the method.31
    38
     Error javadoc JavadocMethod Missing a Javadoc comment.31
    38
     Error misc FinalParameters Parameter options should be final.31
    38
     Error sizes LineLength Line is longer than 80 characters (found 85).32
    +39

    org/springframework/cloud/contract/maven/verifier/stubrunner/RemoteStubRunner.java

    - + - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - + - + -
    Severity Category Rule Message Line
     ErrorjavadocJavadocTypeMissing a Javadoc comment.30
     Error sizes LineLength Line is longer than 80 characters (found 81).33
    40
     Error whitespace FileTabCharacter File contains tab characters (this is the first instance).33
    40
     Error javadoc JavadocVariable Missing a Javadoc comment.33
    40
     Error naming ConstantName Name 'log' must match pattern '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$'.33
    40
     Error javadoc JavadocVariable Missing a Javadoc comment.35
    42
     Error javadoc JavadocMethod Missing a Javadoc comment.37
    44
     Error sizes LineLength Line is longer than 80 characters (found 90).38
    45
     Error misc FinalParameters Parameter aetherStubDownloaderFactory should be final.38
    45
     Error coding HiddenField 'aetherStubDownloaderFactory' hides a field.38
    45
     Error design DesignForExtension Class 'RemoteStubRunner' looks like designed for extension (can be subclassed), but the method 'run' does not have javadoc that explains how to do that safely. If class is not designed for extension consider making the class 'RemoteStubRunner' final or making the method 'run' static/final/abstract/empty, or adding allowed annotation for the method.42
    49
     Error javadoc JavadocMethod Missing a Javadoc comment.42
    49
     Error misc FinalParameters Parameter options should be final.42
    49
     Error misc FinalParameters Parameter repositorySystemSession should be final.43
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).48
     ErrorsizesLineLengthLine is longer than 80 characters (found 88). 50
     Error sizes LineLengthLine is longer than 80 characters (found 88).55
     ErrorsizesLineLengthLine is longer than 80 characters (found 88).57
     ErrorsizesLineLength Line is longer than 80 characters (found 82).52
    59
     Error blocks RightCurly '}' at column 3 should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else, do/while or try/catch/finally).55
    62
     Error sizes LineLength Line is longer than 80 characters (found 93).57
    +64 diff --git a/spring-cloud-contract-maven-plugin/checkstyle.rss b/spring-cloud-contract-maven-plugin/checkstyle.rss index 1a7a2a54e7..50205cee77 100644 --- a/spring-cloud-contract-maven-plugin/checkstyle.rss +++ b/spring-cloud-contract-maven-plugin/checkstyle.rss @@ -26,7 +26,7 @@ under the License. ©2016 - 2019 Spring File: 12, - Errors: 582, + Errors: 539, Warnings: 0, Infos: 0 @@ -55,7 +55,7 @@ under the License. 0 - 116 + 102 @@ -69,7 +69,7 @@ under the License. 0 - 83 + 82 @@ -83,7 +83,7 @@ under the License. 0 - 40 + 37 @@ -97,7 +97,7 @@ under the License. 0 - 34 + 30 @@ -111,7 +111,7 @@ under the License. 0 - 33 + 29 @@ -125,7 +125,7 @@ under the License. 0 - 24 + 23 @@ -139,7 +139,7 @@ under the License. 0 - 46 + 41 @@ -167,7 +167,7 @@ under the License. 0 - 19 + 18 @@ -181,7 +181,7 @@ under the License. 0 - 10 + 9 @@ -195,7 +195,7 @@ under the License. 0 - 20 + 21 @@ -209,7 +209,7 @@ under the License. 0 - 113 + 103 diff --git a/spring-cloud-contract-maven-plugin/complex.html b/spring-cloud-contract-maven-plugin/complex.html index 31fa163576..4ff8b41d5b 100644 --- a/spring-cloud-contract-maven-plugin/complex.html +++ b/spring-cloud-contract-maven-plugin/complex.html @@ -264,44 +264,53 @@

    Project configuration for Spring Cloud Contract Verifier with JUnit tests and stub publishing

    -
                <plugin>
    -                <groupId>org.springframework.cloud</groupId>
    -                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    -                <version>${spring-cloud-verifier-plugin.version}</version>
    -                <executions>
    -                    <execution>
    -                        <goals>
    -                            <goal>convert</goal>
    -                            <goal>generateStubs</goal>
    -                            <goal>generateTests</goal>
    -                        </goals>
    -                        <configuration>
    -                            <contractsDirectory>src/test/contracts</contractsDirectory>
    -                            <basePackageForTests>com.blogspot.toomuchcoding.frauddetection</basePackageForTests>
    -                            <testMode>MOCKMVC</testMode>
    -                            <testFramework>JUNIT</testFramework>
    -                            <classifier>stubs</classifier>
    -                            <nameSuffixForTests>Test</nameSuffixForTests>
    -                            <ruleClassForTests>org.junit.rules.ErrorCollector</ruleClassForTests>
    -                            <staticImports>
    -                                <staticImport>com.blogspot.toomuchcoding.frauddetection.matchers.CustomMatchers.*</staticImport>
    -                            </staticImports>
    -                            <imports>
    -                                <import>com.blogspot.toomuchcoding.frauddetection.matchers.CustomMatchers</import>
    -                            </imports>
    -                            <ignoredFiles>
    -                                <ignoredFile>broken**</ignoredFile>
    -                            </ignoredFiles>
    -                            <excludedFiles>
    -                                <param>shouldMarkClientAsFraud.groovy</param>
    -                            </excludedFiles>
    -                        </configuration>
    -                    </execution>
    -                </executions>
    -                <configuration>
    -                    <baseClassForTests>com.blogspot.toomuchcoding.frauddetection.BaseAccurest</baseClassForTests>
    -                </configuration>
    -            </plugin>
    +
                            <plugin>
    +                                <groupId>org.springframework.cloud</groupId>
    +                                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    +                                <version>${spring-cloud-verifier-plugin.version}</version>
    +                                <executions>
    +                                        <execution>
    +                                                <goals>
    +                                                        <goal>convert</goal>
    +                                                        <goal>generateStubs</goal>
    +                                                        <goal>generateTests</goal>
    +                                                </goals>
    +                                                <configuration>
    +                                                        <contractsDirectory>src/test/contracts</contractsDirectory>
    +                                                        <basePackageForTests>
    +                                                                com.blogspot.toomuchcoding.frauddetection
    +                                                        </basePackageForTests>
    +                                                        <testMode>MOCKMVC</testMode>
    +                                                        <testFramework>JUNIT</testFramework>
    +                                                        <classifier>stubs</classifier>
    +                                                        <nameSuffixForTests>Test</nameSuffixForTests>
    +                                                        <ruleClassForTests>org.junit.rules.ErrorCollector
    +                                                        </ruleClassForTests>
    +                                                        <staticImports>
    +                                                                <staticImport>
    +                                                                        com.blogspot.toomuchcoding.frauddetection.matchers.CustomMatchers.*
    +                                                                </staticImport>
    +                                                        </staticImports>
    +                                                        <imports>
    +                                                                <import>
    +                                                                        com.blogspot.toomuchcoding.frauddetection.matchers.CustomMatchers
    +                                                                </import>
    +                                                        </imports>
    +                                                        <ignoredFiles>
    +                                                                <ignoredFile>broken**</ignoredFile>
    +                                                        </ignoredFiles>
    +                                                        <excludedFiles>
    +                                                                <param>shouldMarkClientAsFraud.groovy</param>
    +                                                        </excludedFiles>
    +                                                </configuration>
    +                                        </execution>
    +                                </executions>
    +                                <configuration>
    +                                        <baseClassForTests>
    +                                                com.blogspot.toomuchcoding.frauddetection.BaseAccurest
    +                                        </baseClassForTests>
    +                                </configuration>
    +                        </plugin>
    @@ -309,26 +318,23 @@

    Base Test class

    -
    /**
    +
    /*
    + * Copyright 2013-2019 the original author or authors.
      *
    - *  Copyright 2013-2019 the original author or authors.
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
      *
    - *  Licensed under the Apache License, Version 2.0 (the "License");
    - *  you may not use this file except in compliance with the License.
    - *  You may obtain a copy of the License at
    + *      http://www.apache.org/licenses/LICENSE-2.0
      *
    - *       http://www.apache.org/licenses/LICENSE-2.0
    - *
    - *  Unless required by applicable law or agreed to in writing, software
    - *  distributed under the License is distributed on an "AS IS" BASIS,
    - *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - *  See the License for the specific language governing permissions and
    - *  limitations under the License.
    - */
    -package com.blogspot.toomuchcoding.frauddetection;
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */package com.blogspot.toomuchcoding.frauddetection;
     
     import io.restassured.module.mockmvc.RestAssuredMockMvc;
    -
     import org.junit.Before;
     
     public class BaseAccurest {
    @@ -346,23 +352,21 @@
     

    Sample additional matcher

    -
    /**
    +
    /*
    + * Copyright 2013-2019 the original author or authors.
      *
    - *  Copyright 2013-2019 the original author or authors.
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
      *
    - *  Licensed under the Apache License, Version 2.0 (the "License");
    - *  you may not use this file except in compliance with the License.
    - *  You may obtain a copy of the License at
    + *      http://www.apache.org/licenses/LICENSE-2.0
      *
    - *       http://www.apache.org/licenses/LICENSE-2.0
    - *
    - *  Unless required by applicable law or agreed to in writing, software
    - *  distributed under the License is distributed on an "AS IS" BASIS,
    - *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - *  See the License for the specific language governing permissions and
    - *  limitations under the License.
    - */
    -package com.blogspot.toomuchcoding.frauddetection.matchers;
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */package com.blogspot.toomuchcoding.frauddetection.matchers;
     
     import org.junit.Assert;
     
    @@ -380,48 +384,49 @@
     

    Sample contract using matcher

    -
    /**
    +
    /*
    + * Copyright 2013-2019 the original author or authors.
      *
    - *  Copyright 2013-2019 the original author or authors.
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
      *
    - *  Licensed under the Apache License, Version 2.0 (the "License");
    - *  you may not use this file except in compliance with the License.
    - *  You may obtain a copy of the License at
    + *      http://www.apache.org/licenses/LICENSE-2.0
      *
    - *       http://www.apache.org/licenses/LICENSE-2.0
    - *
    - *  Unless required by applicable law or agreed to in writing, software
    - *  distributed under the License is distributed on an "AS IS" BASIS,
    - *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    - *  See the License for the specific language governing permissions and
    - *  limitations under the License.
    - */
    -org.springframework.cloud.contract.spec.Contract.make {
    -                                request {
    -                                        method 'PUT'
    -                                        url '/fraudcheck'
    -                                        body("""
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */ org.springframework.cloud.contract.spec.Contract.make {
    +        request {
    +                method 'PUT'
    +                url '/fraudcheck'
    +                body("""
                                                     {
    -                                                "clientPesel":"${value(consumer(regex('[0-9]{10}')), producer('1234567890'))}",
    +                                                "clientPesel":"${
    +                        value(consumer(regex('[0-9]{10}')), producer('1234567890'))
    +                }",
                                                     "loanAmount":123.123
                                                     }
                                             """
    -                                        )
    -                                        headers {
    -                                                header('Content-Type', 'application/vnd.fraud.v1+json')
    -                                        }
    +                )
    +                headers {
    +                        header('Content-Type', 'application/vnd.fraud.v1+json')
    +                }
     
    -                                }
    -                        response {
    -                                status OK()
    -                                body(
    -                                                fraudCheckStatus: "OK",
    -                                                rejectionReason: $(consumer(null), producer(execute('assertThatRejectionReasonIsNull($it)')))
    -                                )
    -                                headers {
    -                                         header('Content-Type': 'application/vnd.fraud.v1+json')
    -                                }
    -                        }
    +        }
    +        response {
    +                status OK()
    +                body(
    +                                fraudCheckStatus: "OK",
    +                                rejectionReason: $(consumer(null),
    +                                                producer(execute('assertThatRejectionReasonIsNull($it)')))
    +                )
    +                headers {
    +                        header('Content-Type': 'application/vnd.fraud.v1+json')
    +                }
    +        }
     
     }
    diff --git a/spring-cloud-contract-maven-plugin/configs.html b/spring-cloud-contract-maven-plugin/configs.html index eacb1ddf1a..4aa3fba5b6 100644 --- a/spring-cloud-contract-maven-plugin/configs.html +++ b/spring-cloud-contract-maven-plugin/configs.html @@ -316,7 +316,9 @@ contracts got deployed.

    <artifactId>spring-cloud-contract-maven-plugin</artifactId> <configuration> <contractsMode>REMOTE</contractsMode> - <contractsRepositoryUrl>http://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl> + <contractsRepositoryUrl> + http://link/to/your/nexus/or/artifactory/or/sth + </contractsRepositoryUrl> <contractDependency> <groupId>com.example.standalone</groupId> <artifactId>contracts</artifactId> diff --git a/spring-cloud-contract-maven-plugin/convert-mojo.html b/spring-cloud-contract-maven-plugin/convert-mojo.html index af0a81b5e4..14e17fa14b 100644 --- a/spring-cloud-contract-maven-plugin/convert-mojo.html +++ b/spring-cloud-contract-maven-plugin/convert-mojo.html @@ -316,7 +316,7 @@ stubs mappings. - Directory containing Spring Cloud Contract Verifier contracts -written using the GroovyDSL
    Default value is: ${project.basedir}/src/test/resources/contracts.
    User property is: spring.cloud.contract.verifier.contractsDirectory.
    +written using the GroovyDSL.
    Default value is: ${project.basedir}/src/test/resources/contracts.
    User property is: spring.cloud.contract.verifier.contractsDirectory.
    @@ -327,7 +327,7 @@ written using the GroovyDSL
    Default value is: ${project.basedir} - -Picks the mode in which stubs will be found and registered
    Default value is: CLASSPATH.
    User property is: contractsMode.
    +Picks the mode in which stubs will be found and registered.
    Default value is: CLASSPATH.
    User property is: contractsMode.
    @@ -340,11 +340,10 @@ written using the GroovyDSL
    Default value is: ${project.basedir} The path in the JAR with all the contracts where contracts for this particular service lay. If not provided will be resolved to -groupid/artifactid. Example:
    -
    - If groupid is com.example and -artifactid is service then the resolved -path will be /com/example/artifactid
    User property is: contractsPath.
    +groupid/artifactid. Example: If groupid +is com.example and artifactid is +service then the resolved path will be +/com/example/artifactid
    User property is: contractsPath.
    @@ -356,7 +355,7 @@ path will be /com/example/artifactid
    User property is: - Map of properties that can be passed to custom -StubDownloaderBuilder
    User property is: contractsProperties.
    +StubDownloaderBuilder.
    User property is: contractsProperties.
    @@ -437,7 +436,7 @@ taken into consideration
    User property is: contractsRepositoryUr - If true then will convert contracts to a YAML -representation
    Default value is: false.
    User property is: convertToYaml.
    +representation.
    Default value is: false.
    User property is: convertToYaml.
    @@ -449,7 +448,7 @@ representation
    Default value is: false.
    User proper - If set to false will NOT delete stubs from a temporary -folder after running tests
    Default value is: true.
    User property is: deleteStubsAfterTest.
    +folder after running tests.
    Default value is: true.
    User property is: deleteStubsAfterTest.
    @@ -534,7 +533,7 @@ create jar with stubs
    Default value is: ${project.build.director

    contractsDirectory:

    Directory containing Spring Cloud Contract Verifier contracts -written using the GroovyDSL
    +written using the GroovyDSL.
      @@ -548,7 +547,7 @@ written using the GroovyDSL

    contractsMode:

    -
    Picks the mode in which stubs will be found and registered
    +
    Picks the mode in which stubs will be found and registered.
      @@ -564,11 +563,10 @@ written using the GroovyDSL
    The path in the JAR with all the contracts where contracts for this particular service lay. If not provided will be resolved to -groupid/artifactid. Example:
    -
    - If groupid is com.example and -artifactid is service then the resolved -path will be /com/example/artifactid
    +groupid/artifactid. Example: If groupid +is com.example and artifactid is +service then the resolved path will be +/com/example/artifactid
      @@ -581,7 +579,7 @@ path will be /com/example/artifactid

    contractsProperties:

    Map of properties that can be passed to custom -StubDownloaderBuilder
    +StubDownloaderBuilder.
      @@ -659,7 +657,7 @@ taken into consideration
      Deprecated. - with 2.1.0 this option is redundant
      If true then will not assert whether a stub / contract -JAR was downloaded from local or remote location
      +JAR was downloaded from local or remote location.
        @@ -674,7 +672,7 @@ JAR was downloaded from local or remote location

        convertToYaml:

        If true then will convert contracts to a YAML -representation
        +representation.
          @@ -689,7 +687,7 @@ representation

          deleteStubsAfterTest:

          If set to false will NOT delete stubs from a temporary -folder after running tests
          +folder after running tests.
            diff --git a/spring-cloud-contract-maven-plugin/generateStubs-mojo.html b/spring-cloud-contract-maven-plugin/generateStubs-mojo.html index faa522e8d3..6426a6d38e 100644 --- a/spring-cloud-contract-maven-plugin/generateStubs-mojo.html +++ b/spring-cloud-contract-maven-plugin/generateStubs-mojo.html @@ -268,7 +268,7 @@

            Description:

            Picks the converted .json files and creates a jar. Requires convert -to be executed first
            +to be executed first.

            Attributes:

            @@ -314,7 +314,7 @@ to be executed first - -Patterns that should not be taken into account for processing
            +Patterns that should not be taken into account for processing.
            @@ -325,7 +325,7 @@ to be executed first - -Set this to "true" to bypass only JAR creation
            Default value is: false.
            User property is: spring.cloud.contract.verifier.jar.skip.
            +Set this to "true" to bypass only JAR creation.
            Default value is: false.
            User property is: spring.cloud.contract.verifier.jar.skip.
            @@ -347,7 +347,7 @@ to be executed first - -Set this to "true" to bypass the whole Verifier execution
            Default value is: false.
            User property is: spring.cloud.contract.verifier.skip.
            +Set this to "true" to bypass the whole Verifier execution.
            Default value is: false.
            User property is: spring.cloud.contract.verifier.skip.
            @@ -369,7 +369,7 @@ to be executed first

          excludedFiles:

          -
          Patterns that should not be taken into account for processing
          +
          Patterns that should not be taken into account for processing.
            @@ -379,7 +379,7 @@ to be executed first

          jarSkip:

          -
          Set this to "true" to bypass only JAR creation
          +
          Set this to "true" to bypass only JAR creation.
            @@ -407,7 +407,7 @@ to be executed first

          skip:

          -
          Set this to "true" to bypass the whole Verifier execution
          +
          Set this to "true" to bypass the whole Verifier execution.
            diff --git a/spring-cloud-contract-maven-plugin/generateTests-mojo.html b/spring-cloud-contract-maven-plugin/generateTests-mojo.html index 2c09c9ab36..94a175e675 100644 --- a/spring-cloud-contract-maven-plugin/generateTests-mojo.html +++ b/spring-cloud-contract-maven-plugin/generateTests-mojo.html @@ -268,7 +268,7 @@

            Description:

            From the provided directory with contracts generates the acceptance -tests on the producer side
            +tests on the producer side.

            Attributes:

            @@ -330,16 +330,12 @@ turned on explicitly will be disabled.
            Default value is: falseA way to override any base class mappings. The keys are regular expressions on the package name of the contract and the values FQN -to a base class for that given expression.
            -
            - Example of a mapping
            -
            - .*.com.example.v1..* -> -com.example.SomeBaseClass
            -
            - When a contract's package matches the provided regular expression -then extending class will be the one provided in the map - in this -case com.example.SomeBaseClass
            User property is: baseClassMappings.
            +to a base class for that given expression. Example of a mapping +.*.com.example.v1..* -> +com.example.SomeBaseClass When a contract's package +matches the provided regular expression then extending class will +be the one provided in the map - in this case +com.example.SomeBaseClass.
            User property is: baseClassMappings.
            @@ -383,7 +379,7 @@ case com.example.SomeBaseClass
            User property is: baseCl - -Picks the mode in which stubs will be found and registered
            Default value is: CLASSPATH.
            User property is: contractsMode.
            +Picks the mode in which stubs will be found and registered.
            Default value is: CLASSPATH.
            User property is: contractsMode.
            @@ -396,11 +392,10 @@ case com.example.SomeBaseClass
            User property is: baseCl The path in the JAR with all the contracts where contracts for this particular service lay. If not provided will be resolved to -groupid/artifactid. Example:
            -
            - If groupid is com.example and -artifactid is service then the resolved -path will be /com/example/artifactid
            User property is: contractsPath.
            +groupid/artifactid. Example: If groupid +is com.example and artifactid is +service then the resolved path will be +/com/example/artifactid
            User property is: contractsPath.
            @@ -412,7 +407,7 @@ path will be /com/example/artifactid
            User property is: - Map of properties that can be passed to custom -StubDownloaderBuilder
            User property is: contractsProperties.
            +StubDownloaderBuilder.
            User property is: contractsProperties.
            @@ -459,7 +454,7 @@ path will be /com/example/artifactid
            User property is: The URL from which a contracts should get downloaded. If not provided but artifactid / coordinates notation was provided then the current Maven's build repositories will be taken into -consideration
            User property is: contractsRepositoryUrl.
            +consideration.
            User property is: contractsRepositoryUrl.
            @@ -493,7 +488,7 @@ consideration
            User property is: contractsRepositoryUrl.
            - If set to false will NOT delete stubs from a temporary -folder after running tests
            Default value is: true.
            User property is: deleteStubsAfterTest.
            +folder after running tests.
            Default value is: true.
            User property is: deleteStubsAfterTest.
            @@ -504,7 +499,7 @@ folder after running tests
            Default value is: true.
            - -Patterns that should not be taken into account for processing
            +Patterns that should not be taken into account for processing.
            @@ -538,7 +533,7 @@ folder after running tests
            Default value is: true.
            - Patterns for which Spring Cloud Contract Verifier should generate -@Ignored tests
            +@Ignored tests.
            @@ -549,7 +544,7 @@ folder after running tests
            Default value is: true.
            - -Imports that should be added to generated tests
            +Imports that should be added to generated tests.
            @@ -560,7 +555,7 @@ folder after running tests
            Default value is: true.
            - -Patterns that should be taken into account for processing
            User property is: includedFiles.
            +Patterns that should be taken into account for processing.
            User property is: includedFiles.
            @@ -645,7 +640,7 @@ last folders to and attach Base to its name.
            User property is- -Static imports that should be added to generated tests
            +Static imports that should be added to generated tests.
            @@ -704,16 +699,12 @@ turned on explicitly will be disabled.
            A way to override any base class mappings. The keys are regular expressions on the package name of the contract and the values FQN -to a base class for that given expression.
            -
            - Example of a mapping
            -
            - .*.com.example.v1..* -> -com.example.SomeBaseClass
            -
            - When a contract's package matches the provided regular expression -then extending class will be the one provided in the map - in this -case com.example.SomeBaseClass
            +to a base class for that given expression. Example of a mapping +.*.com.example.v1..* -> +com.example.SomeBaseClass When a contract's package +matches the provided regular expression then extending class will +be the one provided in the map - in this case +com.example.SomeBaseClass.
              @@ -761,7 +752,7 @@ case com.example.SomeBaseClass

            contractsMode:

            -
            Picks the mode in which stubs will be found and registered
            +
            Picks the mode in which stubs will be found and registered.
              @@ -777,11 +768,10 @@ case com.example.SomeBaseClass
              The path in the JAR with all the contracts where contracts for this particular service lay. If not provided will be resolved to -groupid/artifactid. Example:
              -
              - If groupid is com.example and -artifactid is service then the resolved -path will be /com/example/artifactid
              +groupid/artifactid. Example: If groupid +is com.example and artifactid is +service then the resolved path will be +/com/example/artifactid
                @@ -794,7 +784,7 @@ path will be /com/example/artifactid

                contractsProperties:

                Map of properties that can be passed to custom -StubDownloaderBuilder
                +StubDownloaderBuilder.
                  @@ -845,7 +835,7 @@ path will be /com/example/artifactid
                  The URL from which a contracts should get downloaded. If not provided but artifactid / coordinates notation was provided then the current Maven's build repositories will be taken into -consideration
                  +consideration.
                    @@ -872,7 +862,7 @@ consideration
                    Deprecated. - with 2.1.0 this option is redundant
                    If true then will not assert whether a stub / contract -JAR was downloaded from local or remote location
                    +JAR was downloaded from local or remote location.
                      @@ -887,7 +877,7 @@ JAR was downloaded from local or remote location

                      deleteStubsAfterTest:

                      If set to false will NOT delete stubs from a temporary -folder after running tests
                      +folder after running tests.
                        @@ -901,7 +891,7 @@ folder after running tests

                      excludedFiles:

                      -
                      Patterns that should not be taken into account for processing
                      +
                      Patterns that should not be taken into account for processing.
                        @@ -936,7 +926,7 @@ folder after running tests

                        ignoredFiles:

                        Patterns for which Spring Cloud Contract Verifier should generate -@Ignored tests
                        +@Ignored tests.
                          @@ -946,7 +936,7 @@ folder after running tests

                        imports:

                        -
                        Imports that should be added to generated tests
                        +
                        Imports that should be added to generated tests.
                          @@ -956,7 +946,7 @@ folder after running tests

                        includedFiles:

                        -
                        Patterns that should be taken into account for processing
                        +
                        Patterns that should be taken into account for processing.
                          @@ -1050,7 +1040,7 @@ last folders to and attach Base to its name.

                        staticImports:

                        -
                        Static imports that should be added to generated tests
                        +
                        Static imports that should be added to generated tests.
                          diff --git a/spring-cloud-contract-maven-plugin/junit.html b/spring-cloud-contract-maven-plugin/junit.html index 5f6463acbb..3f3ae4905b 100644 --- a/spring-cloud-contract-maven-plugin/junit.html +++ b/spring-cloud-contract-maven-plugin/junit.html @@ -264,12 +264,12 @@

                          Test dependencies for generated contract verification tests

                          -
                                  <dependency>
                          -            <groupId>org.springframework.cloud</groupId>
                          -            <artifactId>spring-cloud-starter-contract-verifier</artifactId>
                          -            <version>${it-plugin.version}</version>
                          -            <scope>test</scope>
                          -        </dependency>
                          +
                                          <dependency>
                          +                        <groupId>org.springframework.cloud</groupId>
                          +                        <artifactId>spring-cloud-starter-contract-verifier</artifactId>
                          +                        <version>${it-plugin.version}</version>
                          +                        <scope>test</scope>
                          +                </dependency>
                          @@ -277,15 +277,15 @@

                          Project configuration for Spring Cloud Contract Verifier with JUnit tests and stub publishing

                          -
                                      <plugin>
                          -                <groupId>org.springframework.cloud</groupId>
                          -                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                          -                <version>${spring-cloud-verifier-plugin.version}</version>
                          -                <extensions>true</extensions>
                          -                <configuration>
                          -                    <baseClassForTests>hello.BaseAccurest</baseClassForTests>
                          -                </configuration>
                          -            </plugin>
                          +
                                                  <plugin>
                          +                                <groupId>org.springframework.cloud</groupId>
                          +                                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                          +                                <version>${spring-cloud-verifier-plugin.version}</version>
                          +                                <extensions>true</extensions>
                          +                                <configuration>
                          +                                        <baseClassForTests>hello.BaseAccurest</baseClassForTests>
                          +                                </configuration>
                          +                        </plugin>
                          @@ -293,34 +293,31 @@

                          Base Test class

                          -
                          /**
                          +
                          /*
                          + * Copyright 2013-2019 the original author or authors.
                            *
                          - *  Copyright 2013-2019 the original author or authors.
                          + * Licensed under the Apache License, Version 2.0 (the "License");
                          + * you may not use this file except in compliance with the License.
                          + * You may obtain a copy of the License at
                            *
                          - *  Licensed under the Apache License, Version 2.0 (the "License");
                          - *  you may not use this file except in compliance with the License.
                          - *  You may obtain a copy of the License at
                          + *      http://www.apache.org/licenses/LICENSE-2.0
                            *
                          - *       http://www.apache.org/licenses/LICENSE-2.0
                          - *
                          - *  Unless required by applicable law or agreed to in writing, software
                          - *  distributed under the License is distributed on an "AS IS" BASIS,
                          - *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
                          - *  See the License for the specific language governing permissions and
                          - *  limitations under the License.
                          - */
                          -package hello;
                          + * Unless required by applicable law or agreed to in writing, software
                          + * distributed under the License is distributed on an "AS IS" BASIS,
                          + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
                          + * See the License for the specific language governing permissions and
                          + * limitations under the License.
                          + */package hello;
                           
                           import io.restassured.module.mockmvc.RestAssuredMockMvc;
                          -
                           import org.junit.Before;
                           
                           public class BaseAccurest {
                           
                          -    @Before
                          -    public void setup() {
                          -        RestAssuredMockMvc.standaloneSetup(new GreetingController());
                          -    }
                          +        @Before
                          +        public void setup() {
                          +                RestAssuredMockMvc.standaloneSetup(new GreetingController());
                          +        }
                           
                           }
                          diff --git a/spring-cloud-contract-maven-plugin/plugin-info.html b/spring-cloud-contract-maven-plugin/plugin-info.html index 640b050e8e..6eb44bf50f 100644 --- a/spring-cloud-contract-maven-plugin/plugin-info.html +++ b/spring-cloud-contract-maven-plugin/plugin-info.html @@ -284,11 +284,11 @@ stubs mappings. spring-cloud-contract:generateStubs Picks the converted .json files and creates a jar. Requires convert -to be executed first +to be executed first. spring-cloud-contract:generateTests From the provided directory with contracts generates the acceptance -tests on the producer side +tests on the producer side. spring-cloud-contract:help Display help information on @@ -301,7 +301,7 @@ Call mvn spring-cloud-contract:help -Ddetail=true origin. spring-cloud-contract:run -No description. +Mojo for running stubs.

                          System Requirements

                          The following specifies the minimum requirements to run this Maven plugin:

                          diff --git a/spring-cloud-contract-maven-plugin/plugin-management.html b/spring-cloud-contract-maven-plugin/plugin-management.html index 7683d2f075..a8f01a3276 100644 --- a/spring-cloud-contract-maven-plugin/plugin-management.html +++ b/spring-cloud-contract-maven-plugin/plugin-management.html @@ -368,8 +368,8 @@ 3.1.0 org.apache.maven.plugins -maven-release-plugin -2.3.2 +maven-release-plugin +2.5.3 org.apache.maven.plugins maven-resources-plugin diff --git a/spring-cloud-contract-maven-plugin/plugins.html b/spring-cloud-contract-maven-plugin/plugins.html index 17df2df6b1..38f503428d 100644 --- a/spring-cloud-contract-maven-plugin/plugins.html +++ b/spring-cloud-contract-maven-plugin/plugins.html @@ -327,78 +327,82 @@ ArtifactId Version +io.spring.javaformat +spring-javaformat-maven-plugin +0.0.6 + io.takari.maven.plugins takari-lifecycle-plugin 1.13.7 - + org.apache.maven.plugins maven-checkstyle-plugin 3.0.0 - + org.apache.maven.plugins maven-clean-plugin 3.0.0 - + org.apache.maven.plugins maven-compiler-plugin 3.8.0 - + org.apache.maven.plugins maven-deploy-plugin 2.7 - + org.apache.maven.plugins maven-failsafe-plugin 2.22.0 - + org.apache.maven.plugins maven-install-plugin 2.4 - + org.apache.maven.plugins maven-jar-plugin 3.1.0 - + org.apache.maven.plugins maven-javadoc-plugin 3.0.1 - + org.apache.maven.plugins maven-plugin-plugin 3.5 - + org.apache.maven.plugins maven-resources-plugin 3.1.0 - + org.apache.maven.plugins maven-scm-publish-plugin 3.0.0 - + org.apache.maven.plugins maven-site-plugin 3.7.1 - + org.apache.maven.plugins maven-source-plugin 3.0.1 - + org.apache.maven.plugins maven-surefire-plugin 2.22.1 - + org.codehaus.gmavenplus gmavenplus-plugin 1.6.2 - + org.codehaus.plexus plexus-component-metadata 1.7.1 - + org.eluder.coveralls coveralls-maven-plugin 4.3.0 - + org.jacoco jacoco-maven-plugin 0.8.2
                          diff --git a/spring-cloud-contract-maven-plugin/pushStubsToScm-mojo.html b/spring-cloud-contract-maven-plugin/pushStubsToScm-mojo.html index a39a3ae54c..0f392202eb 100644 --- a/spring-cloud-contract-maven-plugin/pushStubsToScm-mojo.html +++ b/spring-cloud-contract-maven-plugin/pushStubsToScm-mojo.html @@ -301,7 +301,7 @@ origin.
                          - -Picks the mode in which stubs will be found and registered
                          Default value is: CLASSPATH.
                          User property is: contractsMode.
                          +Picks the mode in which stubs will be found and registered.
                          Default value is: CLASSPATH.
                          User property is: contractsMode.
                          @@ -313,7 +313,7 @@ origin. - Map of properties that can be passed to custom -StubDownloaderBuilder
                          User property is: contractsProperties.
                          +StubDownloaderBuilder.
                          User property is: contractsProperties.
                          @@ -338,7 +338,7 @@ origin. The URL from which a contracts should get downloaded. If not provided but artifactid / coordinates notation was provided then the current Maven's build repositories will be taken into -consideration
                          User property is: contractsRepositoryUrl.
                          +consideration.
                          User property is: contractsRepositoryUrl.
                          @@ -361,7 +361,7 @@ consideration
                          User property is: contractsRepositoryUrl.
                          - If set to false will NOT delete stubs from a temporary -folder after running tests
                          Default value is: true.
                          User property is: deleteStubsAfterTest.
                          +folder after running tests.
                          Default value is: true.
                          User property is: deleteStubsAfterTest.
                          @@ -383,7 +383,7 @@ folder after running tests
                          Default value is: true.
                          - -Set this to "true" to bypass the whole Verifier execution
                          Default value is: false.
                          User property is: spring.cloud.contract.verifier.skip.
                          +Set this to "true" to bypass the whole Verifier execution.
                          Default value is: false.
                          User property is: spring.cloud.contract.verifier.skip.
                          @@ -394,7 +394,7 @@ folder after running tests
                          Default value is: true.
                          - -Set this to "true" to bypass only JAR creation
                          Default value is: false.
                          User property is: spring.cloud.contract.verifier.publish-stubs-to-scm.skip.
                          +Set this to "true" to bypass only JAR creation.
                          Default value is: false.
                          User property is: spring.cloud.contract.verifier.publish-stubs-to-scm.skip.
                          @@ -404,7 +404,7 @@ folder after running tests
                          Default value is: true.

                          contractsMode:

                          -
                          Picks the mode in which stubs will be found and registered
                          +
                          Picks the mode in which stubs will be found and registered.
                            @@ -419,7 +419,7 @@ folder after running tests
                            Default value is: true.

                            contractsProperties:

                            Map of properties that can be passed to custom -StubDownloaderBuilder
                            +StubDownloaderBuilder.
                              @@ -446,7 +446,7 @@ folder after running tests
                              Default value is: true.
                              The URL from which a contracts should get downloaded. If not provided but artifactid / coordinates notation was provided then the current Maven's build repositories will be taken into -consideration
                              +consideration.
                                @@ -471,7 +471,7 @@ consideration

                                deleteStubsAfterTest:

                                If set to false will NOT delete stubs from a temporary -folder after running tests
                                +folder after running tests.
                                  @@ -499,7 +499,7 @@ folder after running tests

                                skip:

                                -
                                Set this to "true" to bypass the whole Verifier execution
                                +
                                Set this to "true" to bypass the whole Verifier execution.
                                  @@ -513,7 +513,7 @@ folder after running tests

                                taskSkip:

                                -
                                Set this to "true" to bypass only JAR creation
                                +
                                Set this to "true" to bypass only JAR creation.
                                  diff --git a/spring-cloud-contract-maven-plugin/run-mojo.html b/spring-cloud-contract-maven-plugin/run-mojo.html index f460d82231..1b1e9e4834 100644 --- a/spring-cloud-contract-maven-plugin/run-mojo.html +++ b/spring-cloud-contract-maven-plugin/run-mojo.html @@ -267,7 +267,7 @@

                                  Description:

                                  -
                                  (no description)
                                  +
                                  Mojo for running stubs.

                                  Attributes:

                                  @@ -311,7 +311,7 @@ - -HTTP port for the WireMock server that serves stubs
                                  Default value is: 8080.
                                  User property is: spring.cloud.contract.verifier.http.port.
                                  +HTTP port for the WireMock server that serves stubs.
                                  Default value is: 8080.
                                  User property is: spring.cloud.contract.verifier.http.port.
                                  @@ -322,7 +322,7 @@ - -Maximal port at which the stub should start
                                  Default value is: 15000.
                                  User property is: spring.cloud.contract.verifier.http.maxPort.
                                  +Maximal port at which the stub should start.
                                  Default value is: 15000.
                                  User property is: spring.cloud.contract.verifier.http.maxPort.
                                  @@ -333,7 +333,7 @@ - -Minimal port at which the stub should start
                                  Default value is: 10000.
                                  User property is: spring.cloud.contract.verifier.http.minPort.
                                  +Minimal port at which the stub should start.
                                  Default value is: 10000.
                                  User property is: spring.cloud.contract.verifier.http.minPort.
                                  @@ -367,7 +367,7 @@ - List of stubs to be downloaded and ran in a colon separated Ivy -notation
                                  User property is: spring.cloud.contract.verifier.stubs.
                                  +notation.
                                  User property is: spring.cloud.contract.verifier.stubs.
                                  @@ -401,7 +401,7 @@ notation
                                  User property is: spring.cloud.contract.verifier.stubs< - Should the plugin wait for the user to press the key after starting -the stubs
                                  Default value is: true.
                                  User property is: spring.cloud.contract.verifier.wait-for-key-pressed.
                                  +the stubs.
                                  Default value is: true.
                                  User property is: spring.cloud.contract.verifier.wait-for-key-pressed.
                                  @@ -425,7 +425,7 @@ the stubs
                                  Default value is: true.
                                  User property is<

                                httpPort:

                                -
                                HTTP port for the WireMock server that serves stubs
                                +
                                HTTP port for the WireMock server that serves stubs.
                                  @@ -439,7 +439,7 @@ the stubs
                                  Default value is: true.
                                  User property is<

                                maxPort:

                                -
                                Maximal port at which the stub should start
                                +
                                Maximal port at which the stub should start.
                                  @@ -453,7 +453,7 @@ the stubs
                                  Default value is: true.
                                  User property is<

                                minPort:

                                -
                                Minimal port at which the stub should start
                                +
                                Minimal port at which the stub should start.
                                  @@ -496,7 +496,7 @@ the stubs
                                  Default value is: true.
                                  User property is<

                                  stubs:

                                  List of stubs to be downloaded and ran in a colon separated Ivy -notation
                                  +notation.
                                    @@ -533,7 +533,7 @@ notation

                                    waitForKeyPressed:

                                    Should the plugin wait for the user to press the key after starting -the stubs
                                    +the stubs.
                                      diff --git a/spring-cloud-contract-maven-plugin/spock.html b/spring-cloud-contract-maven-plugin/spock.html index fe661881f3..822f7d6129 100644 --- a/spring-cloud-contract-maven-plugin/spock.html +++ b/spring-cloud-contract-maven-plugin/spock.html @@ -264,18 +264,18 @@

                                      Test dependencies for generated contract verification tests

                                      -
                                              <dependency>
                                      -            <groupId>org.spockframework</groupId>
                                      -            <artifactId>spock-core</artifactId>
                                      -            <version>1.0-groovy-2.4</version>
                                      -            <scope>test</scope>
                                      -        </dependency>
                                      -        <dependency>
                                      -            <groupId>org.springframework.cloud</groupId>
                                      -            <artifactId>spring-cloud-starter-contract-verifier</artifactId>
                                      -            <version>${it-plugin.version}</version>
                                      -            <scope>test</scope>
                                      -        </dependency>
                                      +
                                                      <dependency>
                                      +                        <groupId>org.spockframework</groupId>
                                      +                        <artifactId>spock-core</artifactId>
                                      +                        <version>1.0-groovy-2.4</version>
                                      +                        <scope>test</scope>
                                      +                </dependency>
                                      +                <dependency>
                                      +                        <groupId>org.springframework.cloud</groupId>
                                      +                        <artifactId>spring-cloud-starter-contract-verifier</artifactId>
                                      +                        <version>${it-plugin.version}</version>
                                      +                        <scope>test</scope>
                                      +                </dependency>
                                      @@ -283,52 +283,54 @@

                                      Project configuration for Spring Cloud Contract Verifier, Groovy, Spock specifications and stub publishing

                                      -
                                                  <plugin>
                                      -                <groupId>org.springframework.cloud</groupId>
                                      -                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                                      -                <version>${spring-cloud-verifier-plugin.version}</version>
                                      -                <extensions>true</extensions>
                                      -                <configuration>
                                      -                    <baseClassForTests>hello.BaseAccurest</baseClassForTests>
                                      -                    <testFramework>SPOCK</testFramework>
                                      -                </configuration>
                                      -            </plugin>
                                      +
                                                              <plugin>
                                      +                                <groupId>org.springframework.cloud</groupId>
                                      +                                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                                      +                                <version>${spring-cloud-verifier-plugin.version}</version>
                                      +                                <extensions>true</extensions>
                                      +                                <configuration>
                                      +                                        <baseClassForTests>hello.BaseAccurest</baseClassForTests>
                                      +                                        <testFramework>SPOCK</testFramework>
                                      +                                </configuration>
                                      +                        </plugin>
                                       
                                      -            <plugin>
                                      -                <groupId>org.codehaus.gmavenplus</groupId>
                                      -                <artifactId>gmavenplus-plugin</artifactId>
                                      -                <executions>
                                      -                    <execution>
                                      -                        <goals>
                                      -                            <goal>compileTests</goal>
                                      -                        </goals>
                                      -                    </execution>
                                      -                </executions>
                                      -                <configuration>
                                      -                    <testSources>
                                      -                        <testSource>
                                      -                            <directory>${project.basedir}/src/test/groovy</directory>
                                      -                            <includes>
                                      -                                <include>**/*.groovy</include>
                                      -                            </includes>
                                      -                        </testSource>
                                      -                        <testSource>
                                      -                            <directory>${project.build.directory}/generated-test-sources/contracts</directory>
                                      -                            <includes>
                                      -                                <include>**/*.groovy</include>
                                      -                            </includes>
                                      -                        </testSource>
                                      -                    </testSources>
                                      -                </configuration>
                                      -            </plugin>
                                      -            <plugin>
                                      -                <artifactId>maven-surefire-plugin</artifactId>
                                      -                <configuration>
                                      -                    <includes>
                                      -                        <include>**/*Spec.java</include>
                                      -                    </includes>
                                      -                </configuration>
                                      -            </plugin>
                                      + <plugin> + <groupId>org.codehaus.gmavenplus</groupId> + <artifactId>gmavenplus-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>compileTests</goal> + </goals> + </execution> + </executions> + <configuration> + <testSources> + <testSource> + <directory>${project.basedir}/src/test/groovy</directory> + <includes> + <include>**/*.groovy</include> + </includes> + </testSource> + <testSource> + <directory> + ${project.build.directory}/generated-test-sources/contracts + </directory> + <includes> + <include>**/*.groovy</include> + </includes> + </testSource> + </testSources> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <includes> + <include>**/*Spec.java</include> + </includes> + </configuration> + </plugin>
                                      @@ -336,21 +338,20 @@

                                      Base Specification class

                                      -
                                      /**
                                      +
                                      /*
                                      + * Copyright 2013-2019 the original author or authors.
                                        *
                                      - *  Copyright 2013-2019 the original author or authors.
                                      + * Licensed under the Apache License, Version 2.0 (the "License");
                                      + * you may not use this file except in compliance with the License.
                                      + * You may obtain a copy of the License at
                                        *
                                      - *  Licensed under the Apache License, Version 2.0 (the "License");
                                      - *  you may not use this file except in compliance with the License.
                                      - *  You may obtain a copy of the License at
                                      + *      http://www.apache.org/licenses/LICENSE-2.0
                                        *
                                      - *       http://www.apache.org/licenses/LICENSE-2.0
                                      - *
                                      - *  Unless required by applicable law or agreed to in writing, software
                                      - *  distributed under the License is distributed on an "AS IS" BASIS,
                                      - *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
                                      - *  See the License for the specific language governing permissions and
                                      - *  limitations under the License.
                                      + * Unless required by applicable law or agreed to in writing, software
                                      + * distributed under the License is distributed on an "AS IS" BASIS,
                                      + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
                                      + * See the License for the specific language governing permissions and
                                      + * limitations under the License.
                                        */
                                       package hello
                                       
                                      @@ -359,9 +360,9 @@
                                       
                                       class BaseAccurest extends Specification {
                                       
                                      -    def setup() {
                                      -        RestAssuredMockMvc.standaloneSetup(new GreetingController())
                                      -    }
                                      +        def setup() {
                                      +                RestAssuredMockMvc.standaloneSetup(new GreetingController())
                                      +        }
                                       
                                       }
                                      diff --git a/spring-cloud-contract-maven-plugin/usage.html b/spring-cloud-contract-maven-plugin/usage.html index 1a1f794285..5bfdbd3b3f 100644 --- a/spring-cloud-contract-maven-plugin/usage.html +++ b/spring-cloud-contract-maven-plugin/usage.html @@ -319,15 +319,15 @@ the command will be executed.

                                      -
                                                  <plugin>
                                      -                <groupId>org.springframework.cloud</groupId>
                                      -                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                                      -                <version>${spring-cloud-verifier-plugin.version}</version>
                                      -                <extensions>true</extensions>
                                      -                <configuration>
                                      -                    <baseClassForTests>hello.BaseAccurest</baseClassForTests>
                                      -                </configuration>
                                      -            </plugin>
                                      +
                                                              <plugin>
                                      +                                <groupId>org.springframework.cloud</groupId>
                                      +                                <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                                      +                                <version>${spring-cloud-verifier-plugin.version}</version>
                                      +                                <extensions>true</extensions>
                                      +                                <configuration>
                                      +                                        <baseClassForTests>hello.BaseAccurest</baseClassForTests>
                                      +                                </configuration>
                                      +                        </plugin>
                                      diff --git a/spring-cloud-contract.xml b/spring-cloud-contract.xml index 4c2adeac5c..60784d1d7a 100644 --- a/spring-cloud-contract.xml +++ b/spring-cloud-contract.xml @@ -349,19 +349,19 @@ was sent, the message body, and the header). The following example shows a Camel messaging contract expressed in Groovy DSL: -def contractDsl = Contract.make { - label 'some_label' - input { - messageFrom('jms:delete') - messageBody([ - bookName: 'foo' - ]) - messageHeaders { - header('sample', 'header') - } - assertThat('bookWasDeleted()') - } -} + def contractDsl = Contract.make { + label 'some_label' + input { + messageFrom('jms:delete') + messageBody([ + bookName: 'foo' + ]) + messageHeaders { + header('sample', 'header') + } + assertThat('bookWasDeleted()') + } + } The following example shows the same contract expressed in YAML: label: some_label input: @@ -555,7 +555,23 @@ the PUT method. Groovy DSL -package contracts +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package contracts org.springframework.cloud.contract.spec.Contract.make { request { // (1) @@ -563,7 +579,7 @@ org.springframework.cloud.contract.spec.Contract.make { url '/fraudcheck' // (3) body([ // (4) "client.id": $(regex('[0-9]{10}')), - loanAmount: 99999 + loanAmount : 99999 ]) headers { // (5) contentType('application/json') @@ -572,7 +588,7 @@ org.springframework.cloud.contract.spec.Contract.make { response { // (6) status OK() // (7) body([ // (8) - fraudCheckStatus: "FRAUD", + fraudCheckStatus : "FRAUD", "rejection.reason": "Amount too high" ]) headers { // (9) @@ -678,15 +694,14 @@ response: # (7) You get a running WireMock instance/Messaging route that simulates the service. You would like to feed that instance with a proper stub definition. At some point in time, you need to send a request to the Fraud Detection service. -ResponseEntity<FraudServiceResponse> response = - restTemplate.exchange("http://localhost:" + port + "/fraudcheck", HttpMethod.PUT, - new HttpEntity<>(request, httpHeaders), - FraudServiceResponse.class); +ResponseEntity<FraudServiceResponse> response = restTemplate.exchange( + "http://localhost:" + port + "/fraudcheck", HttpMethod.PUT, + new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class); 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. @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.NONE) -@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"}, - stubsMode = StubRunnerProperties.StubsMode.LOCAL) +@AutoConfigureStubRunner(ids = { + "com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL) public class LoanApplicationServiceTests { After that, during the tests, Spring Cloud Contract automatically finds the stubs (simulating the real service) in the Maven repository and exposes them on a configured @@ -874,10 +889,9 @@ amount is received, the system should reject that loan application with some des At some point in time, you need to send a request to the Fraud Detection service. Assume that you need to send the request containing the ID of the client and the amount the client wants to borrow. You want to send it to the /fraudcheck url via the PUT method. -ResponseEntity<FraudServiceResponse> response = - restTemplate.exchange("http://localhost:" + port + "/fraudcheck", HttpMethod.PUT, - new HttpEntity<>(request, httpHeaders), - FraudServiceResponse.class); +ResponseEntity<FraudServiceResponse> response = restTemplate.exchange( + "http://localhost:" + port + "/fraudcheck", HttpMethod.PUT, + new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class); For simplicity, the port of the Fraud Detection service is set to 8080, and the application runs on 8090. If you start the test at this point, it breaks, because no service currently runs on port @@ -896,7 +910,23 @@ is important because the producer’s test base class name references that f Groovy DSL -package contracts +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package contracts org.springframework.cloud.contract.spec.Contract.make { request { // (1) @@ -904,7 +934,7 @@ org.springframework.cloud.contract.spec.Contract.make { url '/fraudcheck' // (3) body([ // (4) "client.id": $(regex('[0-9]{10}')), - loanAmount: 99999 + loanAmount : 99999 ]) headers { // (5) contentType('application/json') @@ -913,7 +943,7 @@ org.springframework.cloud.contract.spec.Contract.make { response { // (6) status OK() // (7) body([ // (8) - fraudCheckStatus: "FRAUD", + fraudCheckStatus : "FRAUD", "rejection.reason": "Amount too high" ]) headers { // (9) @@ -1144,8 +1174,8 @@ collaborators. (Optional step) Because you’re playing with the collaborato can also provide the offline work switch (StubRunnerProperties.StubsMode.LOCAL). @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.NONE) -@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"}, - stubsMode = StubRunnerProperties.StubsMode.LOCAL) +@AutoConfigureStubRunner(ids = { + "com.example:http-server-dsl:+:stubs:6565" }, stubsMode = StubRunnerProperties.StubsMode.LOCAL) public class LoanApplicationServiceTests { Now, when you run your tests, you see something like this: 2016-07-19 14:22:25.403 INFO 41050 --- [ main] o.s.c.c.stubrunner.AetherStubDownloader : Desired version is + - will try to resolve the latest version @@ -1205,12 +1235,29 @@ capitalize fraud. That gives you the FraudBaseAll the generated tests extend that class. Over there, you can set up your Spring Context or whatever is necessary. In this case, use Rest Assured MVC to start the server side FraudDetectionController. -package com.example.fraud; +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.fraud; import io.restassured.module.mockmvc.RestAssuredMockMvc; import org.junit.Before; public class FraudBase { + @Before public void setup() { RestAssuredMockMvc.standaloneSetup(new FraudDetectionController(), @@ -1232,6 +1279,7 @@ public class FraudBase { public void assertThatRejectionReasonIsNull(Object rejectionReason) { assert rejectionReason == null; } + } Now, if you run the ./mvnw clean install, you get something like this: Results : @@ -1563,8 +1611,9 @@ contract files as described throughout this documentation. This repository has t one to one to the contents of the repo. Example of a pom.xml inside the server folder. <?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> @@ -1578,14 +1627,16 @@ one to one to the contents of the repo. <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> - <relativePath /> + <relativePath/> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> - <spring-cloud-contract.version>2.1.1.BUILD-SNAPSHOT</spring-cloud-contract.version> - <spring-cloud-release.version>Greenwich.BUILD-SNAPSHOT</spring-cloud-release.version> + <spring-cloud-contract.version>2.1.1.BUILD-SNAPSHOT + </spring-cloud-contract.version> + <spring-cloud-release.version>Greenwich.BUILD-SNAPSHOT + </spring-cloud-release.version> <excludeBuildFolders>true</excludeBuildFolders> </properties> @@ -1675,7 +1726,8 @@ Those poms are necessary for the consumer side to run mvn clean install stubs of the producer project. The pom.xml in the root folder can look like this: <?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> @@ -1684,7 +1736,9 @@ Those poms are necessary for the consumer side to run mvn clean install <version>0.0.1-SNAPSHOT</version> <name>Contracts</name> - <description>Contains all the Spring Cloud Contracts, well, contracts. JAR used by the producers to generate tests and stubs</description> + <description>Contains all the Spring Cloud Contracts, well, contracts. JAR used by the + producers to generate tests and stubs + </description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> @@ -1716,8 +1770,8 @@ Those poms are necessary for the consumer side to run mvn clean install </project> It’s using the assembly plugin in order to build the JAR with all the contracts. Example of such setup is here: -<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> <id>project</id> <formats> @@ -1764,7 +1818,9 @@ of the JAR containing the contracts: <artifactId>spring-cloud-contract-maven-plugin</artifactId> <configuration> <contractsMode>REMOTE</contractsMode> - <contractsRepositoryUrl>http://link/to/your/nexus/or/artifactory/or/sth</contractsRepositoryUrl> + <contractsRepositoryUrl> + http://link/to/your/nexus/or/artifactory/or/sth + </contractsRepositoryUrl> <contractDependency> <groupId>com.example.standalone</groupId> <artifactId>contracts</artifactId> @@ -2860,7 +2916,7 @@ name of the base class for the matched contract. You have to provide a list call baseClassForTests = "com.example.FooBase" baseClassMappings { baseClassMapping('.*/com/.*', 'com.example.ComBase') - baseClassMapping('.*/bar/.*':'com.example.BarBase') + baseClassMapping('.*/bar/.*': 'com.example.BarBase') } Let’s assume that you have contracts under - src/test/resources/contract/com/ @@ -3940,20 +3996,20 @@ it is resolved as a channel name. For Camel, Groovy DSL -def contractDsl = Contract.make { - label 'some_label' - input { - triggeredBy('bookReturnedTriggered()') - } - outputMessage { - sentTo('activemq:output') - body('''{ "bookName" : "foo" }''') - headers { - header('BOOK-NAME', 'foo') - messagingContentType(applicationJson()) - } - } -} + def contractDsl = Contract.make { + label 'some_label' + input { + triggeredBy('bookReturnedTriggered()') + } + outputMessage { + sentTo('activemq:output') + body('''{ "bookName" : "foo" }''') + headers { + header('BOOK-NAME', 'foo') + messagingContentType(applicationJson()) + } + } + } @@ -3972,7 +4028,7 @@ outputMessage: The following JUnit test is created: -''' + ''' // when: bookReturnedTriggered(); @@ -3988,7 +4044,7 @@ outputMessage: assertThatJson(parsedJson).field("bookName").isEqualTo("foo"); ''' And the following Spock test would be created: -''' + ''' when: bookReturnedTriggered() @@ -4009,27 +4065,27 @@ outputMessage: Groovy DSL -def contractDsl = Contract.make { - label 'some_label' - input { - messageFrom('jms:input') - messageBody([ - bookName: 'foo' - ]) - messageHeaders { - header('sample', 'header') - } - } - outputMessage { - sentTo('jms:output') - body([ - bookName: 'foo' - ]) - headers { - header('BOOK-NAME', 'foo') - } - } -} + def contractDsl = Contract.make { + label 'some_label' + input { + messageFrom('jms:input') + messageBody([ + bookName: 'foo' + ]) + messageHeaders { + header('sample', 'header') + } + } + outputMessage { + sentTo('jms:output') + body([ + bookName: 'foo' + ]) + headers { + header('BOOK-NAME', 'foo') + } + } + } @@ -4051,7 +4107,7 @@ outputMessage: The following JUnit test is created: -''' + ''' // given: ContractVerifierMessage inputMessage = contractVerifierMessaging.create( "{\\"bookName\\":\\"foo\\"}" @@ -4071,7 +4127,7 @@ outputMessage: assertThatJson(parsedJson).field("bookName").isEqualTo("foo"); ''' And the following Spock test would be created: -"""\ + """\ given: ContractVerifierMessage inputMessage = contractVerifierMessaging.create( '''{"bookName":"foo"}''', @@ -4096,19 +4152,19 @@ and: Groovy DSL -def contractDsl = Contract.make { - label 'some_label' - input { - messageFrom('jms:delete') - messageBody([ - bookName: 'foo' - ]) - messageHeaders { - header('sample', 'header') - } - assertThat('bookWasDeleted()') - } -} + def contractDsl = Contract.make { + label 'some_label' + input { + messageFrom('jms:delete') + messageBody([ + bookName: 'foo' + ]) + messageHeaders { + header('sample', 'header') + } + assertThat('bookWasDeleted()') + } + } @@ -4125,7 +4181,7 @@ input: The following JUnit test is created: -''' + ''' // given: ContractVerifierMessage inputMessage = contractVerifierMessaging.create( "{\\"bookName\\":\\"foo\\"}" @@ -4139,7 +4195,7 @@ input: bookWasDeleted(); ''' And the following Spock test would be created: -''' + ''' given: ContractVerifierMessage inputMessage = contractVerifierMessaging.create( \'\'\'{"bookName":"foo"}\'\'\', @@ -4588,7 +4644,7 @@ static class HttpsForFraudDetection extends WireMockHttpServerStubConfigurer { You can then reuse it via the annotation @AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/", - httpServerStubConfigurer = HttpsForFraudDetection) + httpServerStubConfigurer = HttpsForFraudDetection) Whenever an https port is found, it will take precedence over the http one. @@ -4689,11 +4745,20 @@ mappings available for the given server:
                                      Stub Runner JUnit Rule and Stub Runner JUnit5 Extension Stub Runner comes with a JUnit rule thanks to which you can very easily download and run stubs for given group and artifact id: -@ClassRule public static StubRunnerRule rule = new StubRunnerRule() - .repoRoot(repoRoot()) +@ClassRule +public static StubRunnerRule rule = new StubRunnerRule().repoRoot(repoRoot()) .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance") - .downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"); + .downloadStub("org.springframework.cloud.contract.verifier.stubs", + "loanIssuance") + .downloadStub( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer"); + +@BeforeClass +@AfterClass +public static void setupProps() { + System.clearProperty("stubrunner.repository.root"); + System.clearProperty("stubrunner.classifier"); +} There’s also a StubRunnerExtension available for JUnit 5. StubRunnerRule and StubRunnerExtension work in a very similar fashion. After the rule/ extension is executed, Stub Runner connects to your Maven repository and for the given list of dependencies tries to: @@ -4727,6 +4792,11 @@ import java.util.Map; import org.springframework.cloud.contract.spec.Contract; +/** + * Contract for finding registered stubs. + * + * @author Marcin Grzejszczak + */ public interface StubFinder extends StubTrigger { /** @@ -4734,7 +4804,9 @@ public interface StubFinder extends StubTrigger { * stub. * @param groupId - might be null. In that case a search only via artifactId takes * place + * @param artifactId - artifact id of the stub * @return URL of a running stub or throws exception if not found + * @throws StubNotFoundException in case of not finding a stub */ URL findStubUrl(String groupId, String artifactId) throws StubNotFoundException; @@ -4744,22 +4816,25 @@ public interface StubFinder extends StubTrigger { * {@code artifactId}. * @param ivyNotation - Ivy representation of the Maven artifact * @return URL of a running stub or throws exception if not found + * @throws StubNotFoundException in case of not finding a stub */ URL findStubUrl(String ivyNotation) throws StubNotFoundException; /** - * Returns all running stubs + * @return all running stubs */ RunningStubs findAllRunningStubs(); /** - * Returns the list of Contracts + * @return the list of Contracts */ Map<StubConfiguration, Collection<Contract>> getContracts(); } Example of usage in Spock tests: -@ClassRule @Shared StubRunnerRule rule = new StubRunnerRule() +@ClassRule +@Shared +StubRunnerRule rule = new StubRunnerRule() .stubsMode(StubRunnerProperties.StubsMode.REMOTE) .repoRoot(StubRunnerRuleSpec.getResource("/m2repo/repository").toURI().toString()) .downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance") @@ -4789,40 +4864,65 @@ def 'should output mappings to output folder'() { new File("target/outputmappingsforrule", "fraudDetectionServer_${url.port}").exists() } Example of usage in JUnit tests: -@Test -public void should_start_wiremock_servers() throws Exception { - // expect: 'WireMocks are running' - then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")).isNotNull(); + @Test + public void should_start_wiremock_servers() throws Exception { + // expect: 'WireMocks are running' + then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs", + "loanIssuance")).isNotNull(); then(rule.findStubUrl("loanIssuance")).isNotNull(); - then(rule.findStubUrl("loanIssuance")).isEqualTo(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")); - then(rule.findStubUrl("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isNotNull(); - // and: + then(rule.findStubUrl("loanIssuance")).isEqualTo(rule.findStubUrl( + "org.springframework.cloud.contract.verifier.stubs", "loanIssuance")); + then(rule.findStubUrl( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")) + .isNotNull(); + // and: then(rule.findAllRunningStubs().isPresent("loanIssuance")).isTrue(); - then(rule.findAllRunningStubs().isPresent("org.springframework.cloud.contract.verifier.stubs", "fraudDetectionServer")).isTrue(); - then(rule.findAllRunningStubs().isPresent("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isTrue(); - // and: 'Stubs were registered' - then(httpGet(rule.findStubUrl("loanIssuance").toString() + "/name")).isEqualTo("loanIssuance"); - then(httpGet(rule.findStubUrl("fraudDetectionServer").toString() + "/name")).isEqualTo("fraudDetectionServer"); + then(rule.findAllRunningStubs().isPresent( + "org.springframework.cloud.contract.verifier.stubs", + "fraudDetectionServer")).isTrue(); + then(rule.findAllRunningStubs().isPresent( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")) + .isTrue(); + // and: 'Stubs were registered' + then(httpGet(rule.findStubUrl("loanIssuance").toString() + "/name")) + .isEqualTo("loanIssuance"); + then(httpGet(rule.findStubUrl("fraudDetectionServer").toString() + "/name")) + .isEqualTo("fraudDetectionServer"); + } + + private String httpGet(String url) throws Exception { + try (InputStream stream = URI.create(url).toURL().openStream()) { + return StreamUtils.copyToString(stream, Charset.forName("UTF-8")); + } + } + } JUnit 5 Extension example: // Visible for Junit @RegisterExtension static StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() - .repoRoot(repoRoot()) - .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance") - .downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer") - .withMappingsOutputFolder("target/outputmappingsforrule"); + .repoRoot(repoRoot()).stubsMode(StubRunnerProperties.StubsMode.REMOTE) + .downloadStub("org.springframework.cloud.contract.verifier.stubs", + "loanIssuance") + .downloadStub( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer") + .withMappingsOutputFolder("target/outputmappingsforrule"); -@Test -void should_start_WireMock_servers() { - assertThat(stubRunnerExtension.findStubUrl("org.springframework.cloud.contract.verifier.stubs", - "loanIssuance")).isNotNull(); - assertThat(stubRunnerExtension.findStubUrl("loanIssuance")).isNotNull(); - assertThat(stubRunnerExtension.findStubUrl("loanIssuance")).isEqualTo(stubRunnerExtension - .findStubUrl("org.springframework.cloud.contract.verifier.stubs", "loanIssuance")); - assertThat(stubRunnerExtension - .findStubUrl("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer")).isNotNull(); +@BeforeAll +@AfterAll +static void setupProps() { + System.clearProperty("stubrunner.repository.root"); + System.clearProperty("stubrunner.classifier"); +} + +private static String repoRoot() { + try { + return StubRunnerRuleJUnitTest.class.getResource("/m2repo/repository/") + .toURI().toString(); + } + catch (Exception e) { + return ""; + } } Check the Common properties for JUnit and Spring for more information on how to apply global configuration of Stub Runner. @@ -4843,15 +4943,25 @@ JUnit rule.
                                      Fluent API When using the StubRunnerRule or StubRunnerExtension you can add a stub to download and then pass the port for the last downloaded stub. -@ClassRule public static StubRunnerRule rule = new StubRunnerRule() - .repoRoot(repoRoot()) +@ClassRule +public static StubRunnerRule rule = new StubRunnerRule().repoRoot(repoRoot()) .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .downloadStub("org.springframework.cloud.contract.verifier.stubs", "loanIssuance") - .withPort(12345) - .downloadStub("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:12346"); + .downloadStub("org.springframework.cloud.contract.verifier.stubs", + "loanIssuance") + .withPort(12345).downloadStub( + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer:12346"); + +@BeforeClass +@AfterClass +public static void setupProps() { + System.clearProperty("stubrunner.repository.root"); + System.clearProperty("stubrunner.classifier"); +} You can see that for this example the following test is valid: -then(rule.findStubUrl("loanIssuance")).isEqualTo(URI.create("http://localhost:12345").toURL()); -then(rule.findStubUrl("fraudDetectionServer")).isEqualTo(URI.create("http://localhost:12346").toURL()); +then(rule.findStubUrl("loanIssuance")) + .isEqualTo(URI.create("http://localhost:12345").toURL()); +then(rule.findStubUrl("fraudDetectionServer")) + .isEqualTo(URI.create("http://localhost:12346").toURL());
                                      Stub Runner with Spring @@ -4865,15 +4975,20 @@ its methods as presented below: 'foo=${stubrunner.runningstubs.fraudDetectionServer.port}', 'fooWithGroup=${stubrunner.runningstubs.org.springframework.cloud.contract.verifier.stubs.fraudDetectionServer.port}']) @AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/", - httpServerStubConfigurer = HttpsForFraudDetection) + httpServerStubConfigurer = HttpsForFraudDetection) @ActiveProfiles("test") class StubRunnerConfigurationSpec extends Specification { - @Autowired StubFinder stubFinder - @Autowired Environment environment - @StubRunnerPort("fraudDetectionServer") int fraudDetectionServerPort - @StubRunnerPort("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer") int fraudDetectionServerPortWithGroupId - @Value('${foo}') Integer foo + @Autowired + StubFinder stubFinder + @Autowired + Environment environment + @StubRunnerPort("fraudDetectionServer") + int fraudDetectionServerPort + @StubRunnerPort("org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer") + int fraudDetectionServerPortWithGroupId + @Value('${foo}') + Integer foo @BeforeClass @AfterClass @@ -4971,8 +5086,7 @@ class StubRunnerConfigurationSpec extends Specification { return httpStubConfiguration } } -} -// end::test[] +} for the following configuration file: stubrunner: repositoryRoot: classpath:m2repo/repository/ @@ -4985,8 +5099,8 @@ class StubRunnerConfigurationSpec extends Specification { Below you can find an example of achieving the same result by setting values on the annotation. @AutoConfigureStubRunner( ids = ["org.springframework.cloud.contract.verifier.stubs:loanIssuance", - "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer", - "org.springframework.cloud.contract.verifier.stubs:bootService"], + "org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer", + "org.springframework.cloud.contract.verifier.stubs:bootService"], stubsMode = StubRunnerProperties.StubsMode.REMOTE, repositoryRoot = "classpath:m2repo/repository/") Stub Runner Spring registers environment variables in the following manner @@ -5055,8 +5169,7 @@ or DiscoveryClient directly, to call those stubbed servers in stubrunner: idsToServiceIds: ivyNotation: someValueInsideYourCode - fraudDetectionServer: someNameThatShouldMapFraudDetectionServer -# end::ids[] + fraudDetectionServer: someNameThatShouldMapFraudDetectionServer
                                      Test profiles and service discovery In your integration tests you typically don’t want to call neither a discovery service (e.g. Eureka) @@ -5175,7 +5288,8 @@ the Stub Runner server. It will be available at port 8750.@AutoConfigureStu Now let’s assume that we want to start this application so that the stubs get automatically registered. We can do it by running the app java -jar ${SYSTEM_PROPS} stub-runner-boot-eureka-example.jar where ${SYSTEM_PROPS} would contain the following list of properties --Dstubrunner.repositoryRoot=http://repo.spring.io/snapshots (1) --Dstubrunner.cloud.stubbed.discovery.enabled=false (2) --Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org.springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework.cloud.contract.verifier.stubs:bootService (3) --Dstubrunner.idsToServiceIds.fraudDetectionServer=someNameThatShouldMapFraudDetectionServer (4) - -(1) - we tell Stub Runner where all the stubs reside -(2) - we don't want the default behaviour where the discovery service is stubbed. That's why the stub registration will be picked -(3) - we provide a list of stubs to download -(4) - we provide a list of artifactId to serviceId mapping +* -Dstubrunner.repositoryRoot=http://repo.spring.io/snapshots (1) +* -Dstubrunner.cloud.stubbed.discovery.enabled=false (2) +* -Dstubrunner.ids=org.springframework.cloud.contract.verifier.stubs:loanIssuance,org. +* springframework.cloud.contract.verifier.stubs:fraudDetectionServer,org.springframework. +* cloud.contract.verifier.stubs:bootService (3) +* -Dstubrunner.idsToServiceIds.fraudDetectionServer= +* someNameThatShouldMapFraudDetectionServer (4) +* +* (1) - we tell Stub Runner where all the stubs reside (2) - we don't want the default +* behaviour where the discovery service is stubbed. That's why the stub registration will +* be picked (3) - we provide a list of stubs to download (4) - we provide a list of That way your deployed application can send requests to started WireMock servers via the service discovery. Most likely points 1-3 could be set by default in application.yml cause they are not likely to change. That way you can provide only the list of stubs to download whenever you start @@ -5592,6 +5708,11 @@ That way the only remaining framework is Spring AMQP. import java.util.Collection; import java.util.Map; +/** + * Contract for triggering stub messages. + * + * @author Marcin Grzejszczak + */ public interface StubTrigger { /** @@ -5599,6 +5720,8 @@ public interface StubTrigger { * You can use only {@code artifactId} too. * * Feature related to messaging. + * @param ivyNotation ivy notation of a stub + * @param labelName name of the label to trigger * @return true - if managed to run a trigger */ boolean trigger(String ivyNotation, String labelName); @@ -5607,6 +5730,7 @@ public interface StubTrigger { * Triggers an event by a given label. * * Feature related to messaging. + * @param labelName name of the label to trigger * @return true - if managed to run a trigger */ boolean trigger(String labelName); @@ -5620,9 +5744,8 @@ public interface StubTrigger { boolean trigger(); /** - * Returns a mapping of ivy notation of a dependency to all the labels it has. - * * Feature related to messaging. + * @return a mapping of ivy notation of a dependency to all the labels it has. */ Map<String, Collection<String>> labels(); @@ -5753,7 +5876,8 @@ receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
                                      Scenario 2 (output triggered by input) Since the route is set for you it’s enough to just send a message to the jms:output destination. -producerTemplate.sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header']) +producerTemplate. + sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header']) Next we’ll want to listen to the output of the message sent to jms:output Exchange receivedMessage = consumerTemplate.receive('jms:output', 5000) And the received message would pass the following assertions @@ -5764,7 +5888,8 @@ receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
                                      Scenario 3 (input with no output) Since the route is set for you it’s enough to just send a message to the jms:output destination. -producerTemplate.sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header']) +producerTemplate. + sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header'])
                                      @@ -5843,9 +5968,9 @@ classpath. Remember to annotate your test class with @AutoConfigureStub } and the following Spring Integration Route: <?xml version="1.0" encoding="UTF-8"?> -<beans:beans xmlns="http://www.springframework.org/schema/integration" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" + xmlns="http://www.springframework.org/schema/integration" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/integration @@ -6105,29 +6230,29 @@ to disable them explicitly by setting the stubrunner.stream.enabled=fa └── shouldProduceValidPersonData.groovy Consider the following contract: Contract.make { - // Human readable description - description 'Should produce valid person data' - // Label by means of which the output message can be triggered - label 'contract-test.person.created.event' - // input to the contract - input { - // the contract will be triggered by a method - triggeredBy('createPerson()') - } - // output message of the contract - outputMessage { - // destination to which the output message will be sent - sentTo 'contract-test.exchange' - headers { - header('contentType': 'application/json') - header('__TypeId__': 'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person') - } - // the body of the output message - body ([ - id: $(consumer(9), producer(regex("[0-9]+"))), - name: "me" - ]) - } + // Human readable description + description 'Should produce valid person data' + // Label by means of which the output message can be triggered + label 'contract-test.person.created.event' + // input to the contract + input { + // the contract will be triggered by a method + triggeredBy('createPerson()') + } + // output message of the contract + outputMessage { + // destination to which the output message will be sent + sentTo 'contract-test.exchange' + headers { + header('contentType': 'application/json') + header('__TypeId__': 'org.springframework.cloud.contract.stubrunner.messaging.amqp.Person') + } + // the body of the output message + body([ + id : $(consumer(9), producer(regex("[0-9]+"))), + name: "me" + ]) + } } Now consider the following Spring configuration: stubrunner: @@ -6164,7 +6289,7 @@ public SimpleMessageListenerContainer simpleMessageListenerContainer( return container; } Also, the following annotated listener matches and is invoked: -@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "test.queue"), exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true"))) +@RabbitListener(bindings = @QueueBinding(value = @Queue("test.queue"), exchange = @Exchange(value = "contract-test.exchange", ignoreDeclarationExceptions = "true"))) public void handlePerson(Person person) { this.person = person; } @@ -6305,8 +6430,8 @@ following code shows an example: Groovy DSL - org.springframework.cloud.contract.spec.Contract.make { - description(''' + org.springframework.cloud.contract.spec.Contract.make { + description(''' given: An input when: @@ -6314,7 +6439,7 @@ when: then: Output ''') - } + } @@ -6433,7 +6558,23 @@ following resources in our project. Groovy DSL -import org.springframework.cloud.contract.spec.Contract +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import org.springframework.cloud.contract.spec.Contract Contract.make { request { @@ -6508,16 +6649,16 @@ Contract.make { YAML request: - url: /1 - method: PUT - headers: - Content-Type: application/octet-stream - bodyFromFileAsBytes: request.pdf + url: /1 + method: PUT + headers: + Content-Type: application/octet-stream + bodyFromFileAsBytes: request.pdf response: - status: 200 - bodyFromFileAsBytes: response.pdf - headers: - Content-Type: application/octet-stream + status: 200 + bodyFromFileAsBytes: response.pdf + headers: + Content-Type: application/octet-stream @@ -6861,7 +7002,7 @@ body: Content-Type: multipart/form-data;boundary=AaB03x multipart: params: - # key (parameter name), value (parameter value) pair + # key (parameter name), value (parameter value) pair formParameter: '"formParameterValue"' someBooleanParameter: true named: @@ -7076,25 +7217,25 @@ need to use patterns and not exact values both for your test and your server sid do so, then the contract engine automatically provides the generated string that matches the provided regular expression. The following code shows an example: org.springframework.cloud.contract.spec.Contract.make { - request { - method 'PUT' - url value(consumer(regex('/foo/[0-9]{5}'))) - body([ - requestElement: $(consumer(regex('[0-9]{5}'))) - ]) - headers { - header('header', $(consumer(regex('application\\/vnd\\.fraud\\.v1\\+json;.*')))) - } - } - response { - status OK() - body([ - responseElement: $(producer(regex('[0-9]{7}'))) - ]) - headers { - contentType("application/vnd.fraud.v1+json") - } - } + request { + method 'PUT' + url value(consumer(regex('/foo/[0-9]{5}'))) + body([ + requestElement: $(consumer(regex('[0-9]{5}'))) + ]) + headers { + header('header', $(consumer(regex('application\\/vnd\\.fraud\\.v1\\+json;.*')))) + } + } + response { + status OK() + body([ + responseElement: $(producer(regex('[0-9]{7}'))) + ]) + headers { + contentType("application/vnd.fraud.v1+json") + } + } } In the preceding example, the opposite side of the communication has the respective data generated for request and response. @@ -7108,21 +7249,29 @@ protected static final Pattern INTEGER = Pattern.compile('-?(\\d+)') protected static final Pattern POSITIVE_INT = Pattern.compile('([1-9]\\d*)') protected static final Pattern DOUBLE = Pattern.compile('-?(\\d*\\.\\d+)') protected static final Pattern HEX = Pattern.compile('[a-fA-F0-9]+') -protected static final Pattern IP_ADDRESS = Pattern.compile('([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])') -protected static final Pattern HOSTNAME_PATTERN = Pattern.compile('((http[s]?|ftp):/)/?([^:/\\s]+)(:[0-9]{1,5})?') -protected static final Pattern EMAIL = Pattern.compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}') +protected static final Pattern IP_ADDRESS = Pattern. + compile('([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])') +protected static final Pattern HOSTNAME_PATTERN = Pattern. + compile('((http[s]?|ftp):/)/?([^:/\\s]+)(:[0-9]{1,5})?') +protected static final Pattern EMAIL = Pattern. + compile('[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}') protected static final Pattern URL = UrlHelper.URL protected static final Pattern HTTPS_URL = UrlHelper.HTTPS_URL -protected static final Pattern UUID = Pattern.compile('[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}') -protected static final Pattern ANY_DATE = Pattern.compile('(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])') -protected static final Pattern ANY_DATE_TIME = Pattern.compile('([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])') -protected static final Pattern ANY_TIME = Pattern.compile('(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])') +protected static final Pattern UUID = Pattern. + compile('[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}') +protected static final Pattern ANY_DATE = Pattern. + compile('(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])') +protected static final Pattern ANY_DATE_TIME = Pattern. + compile('([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])') +protected static final Pattern ANY_TIME = Pattern. + compile('(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])') protected static final Pattern NON_EMPTY = Pattern.compile(/[\S\s]+/) protected static final Pattern NON_BLANK = Pattern.compile(/^\s*\S[\S\s]*/) -protected static final Pattern ISO8601_WITH_OFFSET = Pattern.compile(/([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d{3})?(Z|[+-][01]\d:[0-5]\d)/) +protected static final Pattern ISO8601_WITH_OFFSET = Pattern. + compile(/([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d{3})?(Z|[+-][01]\d:[0-5]\d)/) -protected static Pattern anyOf(String... values){ - return Pattern.compile(values.collect({"^$it\$"}).join("|")) +protected static Pattern anyOf(String... values) { + return Pattern.compile(values.collect({ "^$it\$" }).join("|")) } RegexProperty onlyAlphaUnicode() { @@ -7173,7 +7322,7 @@ RegexProperty httpsUrl() { return new RegexProperty(HTTPS_URL).asString() } -RegexProperty uuid(){ +RegexProperty uuid() { return new RegexProperty(UUID).asString() } @@ -7202,28 +7351,28 @@ RegexProperty nonBlank() { } In your contract, you can use it as shown in the following example: Contract dslWithOptionalsInString = Contract.make { - priority 1 - request { - method POST() - url '/users/password' - headers { - contentType(applicationJson()) - } - body( - email: $(consumer(optional(regex(email()))), producer('abc@abc.com')), - callback_url: $(consumer(regex(hostname())), producer('http://partners.com')) - ) - } - response { - status 404 - headers { - contentType(applicationJson()) - } - body( - code: value(consumer("123123"), producer(optional("123123"))), - message: "User not found by email = [${value(producer(regex(email())), consumer('not.existing@user.com'))}]" - ) - } + priority 1 + request { + method POST() + url '/users/password' + headers { + contentType(applicationJson()) + } + body( + email: $(consumer(optional(regex(email()))), producer('abc@abc.com')), + callback_url: $(consumer(regex(hostname())), producer('http://partners.com')) + ) + } + response { + status 404 + headers { + contentType(applicationJson()) + } + body( + code: value(consumer("123123"), producer(optional("123123"))), + message: "User not found by email = [${value(producer(regex(email())), consumer('not.existing@user.com'))}]" + ) + } } To make matters even simpler you can use a set of predefined objects that will automatically assume that you want a regular expression to be passed. All of those methods start with any prefix: @@ -7277,25 +7426,25 @@ T anyOf(String... values) outputMessage { sentTo 'topic.rateablequote' body([ - alpha: $(anyAlphaUnicode()), - number: $(anyNumber()), - anInteger: $(anyInteger()), - positiveInt: $(anyPositiveInt()), - aDouble: $(anyDouble()), - aBoolean: $(aBoolean()), - ip: $(anyIpAddress()), - hostname: $(anyHostname()), - email: $(anyEmail()), - url: $(anyUrl()), - httpsUrl: $(anyHttpsUrl()), - uuid: $(anyUuid()), - date: $(anyDate()), - dateTime: $(anyDateTime()), - time: $(anyTime()), + alpha : $(anyAlphaUnicode()), + number : $(anyNumber()), + anInteger : $(anyInteger()), + positiveInt : $(anyPositiveInt()), + aDouble : $(anyDouble()), + aBoolean : $(aBoolean()), + ip : $(anyIpAddress()), + hostname : $(anyHostname()), + email : $(anyEmail()), + url : $(anyUrl()), + httpsUrl : $(anyHttpsUrl()), + uuid : $(anyUuid()), + date : $(anyDate()), + dateTime : $(anyDateTime()), + time : $(anyTime()), iso8601WithOffset: $(anyIso8601WithOffset()), - nonBlankString: $(anyNonBlankString()), - nonEmptyString: $(anyNonEmptyString()), - anyOf: $(anyOf('foo', 'bar')) + nonBlankString : $(anyNonBlankString()), + nonEmptyString : $(anyNonEmptyString()), + anyOf : $(anyOf('foo', 'bar')) ]) } } @@ -7343,7 +7492,7 @@ optional parameters only for the following: By wrapping a part of the body with the optional() method, you create a regular expression that must be present 0 or more times. If you use Spock for, the following test would be generated from the previous example: -""" + """ given: def request = given() .header("Content-Type", "application/json") @@ -7361,7 +7510,7 @@ expression that must be present 0 or more times. assertThatJson(parsedJson).field("['code']").matches("(123123)?") """ The following stub would also be generated: -''' + ''' { "request" : { "url" : "/users/password", @@ -7405,13 +7554,13 @@ following code shows an example of the contract portion of the test case: TestWireMockExtensions.groovy -package org.springframework.cloud.contract.verifier.dsl.wiremock +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.dsl.wiremock import com.github.tomakehurst.wiremock.extension.Extension @@ -8224,7 +8389,7 @@ response: valueWithMinEmpty: [] valueWithMaxEmpty: [] key: - 'complex.key' : 'foo' + 'complex.key': 'foo' nulValue: null matchers: headers: @@ -8362,7 +8527,7 @@ statically imported to your tests. Notice that the byCommand the method name and passed the proper JSON path as a parameter to it. The resulting WireMock stub is in the following example: - ''' + ''' { "request" : { "urlPath" : "/get", @@ -8480,7 +8645,7 @@ content type set. Otherwise, the default of application/octet-streamIn order to use JAX-RS mode, use the following settings: testMode == 'JAXRSCLIENT' The following example shows a generated test API: -''' + ''' // when: Response response = webTarget .path("/users") @@ -8737,19 +8902,19 @@ method should be used, with the desired xPath provided as the and the appropriate MatchingType as second. All the body matchers apart from byType() are supported. Here is an example of a Groovy DSL contract with XML response body: Contract.make { - request { - method GET() - urlPath '/get' - headers { - contentType(applicationXml()) - } - } - response { - status(OK()) - headers { - contentType(applicationXml()) - } - body """ + request { + method GET() + urlPath '/get' + headers { + contentType(applicationXml()) + } + } + response { + status(OK()) + headers { + contentType(applicationXml()) + } + body """ <test> <duck type='xtype'>123</duck> <alpha>abc</alpha> @@ -8766,22 +8931,22 @@ and the appropriate MatchingType as second. All the body matc <valueWithoutAMatcher>foo</valueWithoutAMatcher> <key><complex>foo</complex></key> </test>""" - bodyMatchers { - xPath('/test/duck/text()', byRegex("[0-9]{3}")) - xPath('/test/duck/text()', byCommand('test($it)')) - xPath('/test/duck/xxx', byNull()) - xPath('/test/duck/text()', byEquality()) - xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode())) - xPath('/test/alpha/text()', byEquality()) - xPath('/test/number/text()', byRegex(number())) - xPath('/test/date/text()', byDate()) - xPath('/test/dateTime/text()', byTimestamp()) - xPath('/test/time/text()', byTime()) - xPath('/test/*/complex/text()', byEquality()) - xPath('/test/duck/@type', byEquality()) - } - } - } + bodyMatchers { + xPath('/test/duck/text()', byRegex("[0-9]{3}")) + xPath('/test/duck/text()', byCommand('test($it)')) + xPath('/test/duck/xxx', byNull()) + xPath('/test/duck/text()', byEquality()) + xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode())) + xPath('/test/alpha/text()', byEquality()) + xPath('/test/number/text()', byRegex(number())) + xPath('/test/date/text()', byDate()) + xPath('/test/dateTime/text()', byTimestamp()) + xPath('/test/time/text()', byTime()) + xPath('/test/*/complex/text()', byEquality()) + xPath('/test/duck/@type', byEquality()) + } + } + } And below is an example of a YAML contract with XML request and response bodies: include::{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml Here is an example of an automatically generated test for XML response body: @@ -8903,7 +9068,7 @@ example: messageFrom('input') // has the following body messageBody([ - bookName: 'foo' + bookName: 'foo' ]) // and the following headers messageHeaders { @@ -8913,7 +9078,7 @@ example: outputMessage { sentTo('output') body([ - bookName: 'foo' + bookName: 'foo' ]) headers { header('BOOK-NAME', 'foo') @@ -8966,24 +9131,24 @@ use those paradigms in messaging. In addition, Spring Cloud Contract Verifier al provides the consumer and producer methods, as presented in the following example (note that you can use either $ or value methods to provide consumer and producer parts): -Contract.make { - label 'some_label' - input { - messageFrom value(consumer('jms:output'), producer('jms:input')) - messageBody([ - bookName: 'foo' - ]) - messageHeaders { - header('sample', 'header') - } - } - outputMessage { - sentTo $(consumer('jms:input'), producer('jms:output')) - body([ - bookName: 'foo' - ]) - } -} + Contract.make { + label 'some_label' + input { + messageFrom value(consumer('jms:output'), producer('jms:input')) + messageBody([ + bookName: 'foo' + ]) + messageHeaders { + header('sample', 'header') + } + } + outputMessage { + sentTo $(consumer('jms:input'), producer('jms:output')) + body([ + bookName: 'foo' + ]) + } + }
                                      Common @@ -9003,25 +9168,25 @@ following example: import org.springframework.cloud.contract.spec.Contract [ - Contract.make { - name("should post a user") - request { - method 'POST' - url('/users/1') - } - response { - status OK() - } - }, - Contract.make { - request { - method 'POST' - url('/users/2') - } - response { - status OK() - } - } + Contract.make { + name("should post a user") + request { + method 'POST' + url('/users/1') + } + response { + status OK() + } + }, + Contract.make { + request { + method 'POST' + url('/users/2') + } + response { + status OK() + } + } ] @@ -9139,7 +9304,6 @@ testCompile 'org.springframework.restdocs:spring-restdocs-mockmvc'package com.example.fraud; import io.restassured.module.mockmvc.RestAssuredMockMvc; - import org.junit.Before; import org.junit.Rule; import org.junit.rules.TestName; @@ -9164,24 +9328,26 @@ public abstract class FraudBaseWithWebAppSetup { @Rule public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(OUTPUT); - @Rule public TestName testName = new TestName(); + @Rule + public TestName testName = new TestName(); @Autowired private WebApplicationContext context; @Before public void setup() { - RestAssuredMockMvc.mockMvc(MockMvcBuilders.webAppContextSetup(this.context) - .apply(documentationConfiguration(this.restDocumentation)) - .alwaysDo(document(getClass().getSimpleName() + "_" + testName.getMethodName())) - .build()); + RestAssuredMockMvc.mockMvc(MockMvcBuilders.webAppContextSetup(this.context) + .apply(documentationConfiguration(this.restDocumentation)) + .alwaysDo(document( + getClass().getSimpleName() + "_" + testName.getMethodName())) + .build()); } protected void assertThatRejectionReasonIsNull(Object rejectionReason) { assert rejectionReason == null; } -} -// end::base_class[] + +} In case you are using the standalone setup, you can set up RestAssuredMockMvc like this: package com.example.fraud; @@ -9189,6 +9355,7 @@ import io.restassured.module.mockmvc.RestAssuredMockMvc; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TestName; + import org.springframework.restdocs.JUnitRestDocumentation; import org.springframework.test.web.servlet.setup.MockMvcBuilders; @@ -9202,17 +9369,19 @@ public abstract class FraudBaseWithStandaloneSetup { @Rule public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(OUTPUT); - @Rule public TestName testName = new TestName(); + @Rule + public TestName testName = new TestName(); @Before public void setup() { - RestAssuredMockMvc.standaloneSetup(MockMvcBuilders.standaloneSetup(new FraudDetectionController()) + RestAssuredMockMvc.standaloneSetup(MockMvcBuilders + .standaloneSetup(new FraudDetectionController()) .apply(documentationConfiguration(this.restDocumentation)) - .alwaysDo(document(getClass().getSimpleName() + "_" + testName.getMethodName()))); + .alwaysDo(document( + getClass().getSimpleName() + "_" + testName.getMethodName()))); } -} -// end::base_class[] +} You don’t need to specify the output directory for the generated snippets since version 1.2.0.RELEASE of Spring REST Docs. @@ -9516,7 +9685,7 @@ structure converter. The following code listing shows the ContractConve * Converter to be used to convert FROM {@link File} TO {@link Contract} * and from {@link Contract} to {@code T} * - * @param <T> - type to which we want to convert the contract + * @param <T > - type to which we want to convert the contract * * @author Marcin Grzejszczak * @since 1.1.0 @@ -9622,7 +9791,7 @@ set a metaData entry in the Pact file, with key sent "combine": "AND" } }, - "body" : { + "body": { "$.clientId": { "matchers": [ { @@ -9793,14 +9962,30 @@ current Pact version that you use. way the verifier builds Java tests, you can register your own implementation. The SingleTestGenerator interface lets you register your own implementation. The following code listing shows the SingleTestGenerator interface: - * - * @param properties - properties passed to the plugin - * @param listOfFiles - list of parsed contracts with additional metadata - * @param className - the name of the generated test class - * @param classPackage - the name of the package in which the test class should be stored +package org.springframework.cloud.contract.verifier.builder + + +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties +import org.springframework.cloud.contract.verifier.file.ContractMetadata + +/** + * Builds a single test. + * + * @since 1.1.0 + */ +trait SingleTestGenerator { + + /** + * Creates contents of a single test class in which all test scenarios from + * the contract metadata should be placed. + * + * @param properties - properties passed to the plugin + * @param listOfFiles - list of parsed contracts with additional metadata + * @param className - the name of the generated test class + * @param classPackage - the name of the package in which the test class should be stored * @param includedDirectoryRelativePath - relative path to the included directory * @return contents of a single test class - * @deprecated use {@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)} + * @deprecated use{@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)} */ @Deprecated abstract String buildClass(ContractVerifierConfigProperties properties, @@ -9810,15 +9995,18 @@ following code listing shows the SingleTestGenerator interfac * Creates contents of a single test class in which all test scenarios from * the contract metadata should be placed. * - * @param properties - properties passed to the plugin - * @param listOfFiles - list of parsed contracts with additional metadata - * @param generatedClassData - information about the generated class + * @param properties - properties passed to the plugin + * @param listOfFiles - list of parsed contracts with additional metadata + * @param generatedClassData - information about the generated class * @param includedDirectoryRelativePath - relative path to the included directory * @return contents of a single test class */ String buildClass(ContractVerifierConfigProperties properties, Collection<ContractMetadata> listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) { - return buildClass(properties, listOfFiles, generatedClassData.className, generatedClassData.classPackage, includedDirectoryRelativePath) + String className = generatedClassData.className + String classPackage = generatedClassData.classPackage + String path = includedDirectoryRelativePath + return buildClass(properties, listOfFiles, className, classPackage, path) } /** @@ -9854,6 +10042,7 @@ own implementation of the StubGenerator interface. The follow package org.springframework.cloud.contract.verifier.converter import groovy.transform.CompileStatic + import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.file.ContractMetadata @@ -9866,18 +10055,18 @@ import org.springframework.cloud.contract.verifier.file.ContractMetadata interface StubGenerator { /** - * Returns {@code true} if the converter can handle the file to convert it into a stub. + * @return {@code true} if the converter can handle the file to convert it into a stub. */ boolean canHandleFileName(String fileName) /** - * Returns the collection of converted contracts into stubs. One contract can + * @return the collection of converted contracts into stubs. One contract can * result in multiple stubs. */ Map<Contract, String> convertContents(String rootName, ContractMetadata content) /** - * Returns the name of the converted stub file. If you have multiple contracts + * @return the name of the converted stub file. If you have multiple contracts * in a single file then a prefix will be added to the generated file. If you * provide the {@link Contract#name} field then that field will override the * generated file name. @@ -9960,17 +10149,19 @@ class MocoHttpServerStub implements HttpServerStub { @Override HttpServerStub registerMappings(Collection<File> stubFiles) { List<RunnerSetting> settings = stubFiles.findAll { it.name.endsWith("json") } - .collect { + .collect { log.info("Trying to parse [${it.name}]") try { - return RunnerSetting.aRunnerSetting().withStream(it.newInputStream()).build() - } catch (Exception e) { + return RunnerSetting.aRunnerSetting().withStream(it.newInputStream()). + build() + } + catch (Exception e) { log.warn("Exception occurred while trying to parse file [${it.name}]", e) return null } }.findAll { it } this.runner = JsonRunner.newJsonRunnerWithSetting(settings, - HttpArgs.httpArgs().withPort(this.port).build()) + HttpArgs.httpArgs().withPort(this.port).build()) this.runner.run() this.started = true return this @@ -10172,6 +10363,12 @@ public class WiremockForDocsTests { @Autowired private Service service; + @Before + public void setup() { + this.service.setBase("http://localhost:" + + this.environment.getProperty("wiremock.server.port")); + } + // Using the WireMock APIs in the normal way: @Test public void contextLoads() throws Exception { @@ -10182,8 +10379,7 @@ public class WiremockForDocsTests { assertThat(this.service.go()).isEqualTo("Hello World!"); } -} -// end::wiremock_test2[] +} To start the stub server on a different port use (for example), @AutoConfigureWireMock(port=9999). For a random port, use a value of 0. The stub server port can be bound in the test application context with the "wiremock.server.port" @@ -10253,15 +10449,15 @@ public class WiremockForDocsClassRuleTests { public static WireMockClassRule wiremock = new WireMockClassRule( WireMockSpring.options().dynamicPort()); + // A service that calls out over HTTP to wiremock's port + @Autowired + private Service service; + @Before public void setup() { this.service.setBase("http://localhost:" + wiremock.port()); } - // A service that calls out over HTTP to wiremock's port - @Autowired - private Service service; - // Using the WireMock APIs in the normal way: @Test public void contextLoads() throws Exception { @@ -10272,8 +10468,7 @@ public class WiremockForDocsClassRuleTests { assertThat(this.service.go()).isEqualTo("Hello World!"); } -} -// end::wiremock_test2[] +} The @ClassRule means that the server shuts down after all the methods in this class have been run.