此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 spring-cloud-contract 4.2.0spring-doc.cadn.net.cn

Maven 项目

添加 Maven 插件

要添加 Spring Cloud Contract BOM,请在pom.xml文件:spring-doc.cadn.net.cn

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-dependencies</artifactId>
	<version>${spring-cloud-contract.version}</version>
	<type>pom</type>
	<scope>import</scope>
</dependency>

接下来,添加Spring Cloud Contract VerifierMaven 插件,如下所示:spring-doc.cadn.net.cn

<plugin>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-maven-plugin</artifactId>
	<version>${spring-cloud-contract.version}</version>
	<extensions>true</extensions>
	<configuration>
		<packageWithBaseClasses>com.example.fraud</packageWithBaseClasses>
	</configuration>
</plugin>

有时,无论选择哪种 IDE,您都可以看到target/generated-test-source文件夹在 IDE 的类路径中不可见。为确保它始终存在,您可以将以下条目添加到pom.xmlspring-doc.cadn.net.cn

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>build-helper-maven-plugin</artifactId>
	<executions>
		<execution>
			<id>add-source</id>
			<phase>generate-test-sources</phase>
			<goals>
				<goal>add-test-source</goal>
			</goals>
			<configuration>
				<sources>
					<source>${project.build.directory}/generated-test-sources/contracts/</source>
				</sources>
			</configuration>
		</execution>
	</executions>
</plugin>

Maven 和 Rest Assured 2.0

默认情况下,Rest Assured 3.x 将添加到 Classpath 中。但是,您可以使用 Rest 通过将 2.x 添加到 plugins 类路径来保证 2.x,如下所示:spring-doc.cadn.net.cn

<plugin>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <version>${spring-cloud-contract.version}</version>
    <extensions>true</extensions>
    <configuration>
        <packageWithBaseClasses>com.example</packageWithBaseClasses>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-contract-verifier</artifactId>
            <version>${spring-cloud-contract.version}</version>
        </dependency>
        <dependency>
           <groupId>com.jayway.restassured</groupId>
           <artifactId>rest-assured</artifactId>
           <version>2.5.0</version>
           <scope>compile</scope>
        </dependency>
        <dependency>
           <groupId>com.jayway.restassured</groupId>
           <artifactId>spring-mock-mvc</artifactId>
           <version>2.5.0</version>
           <scope>compile</scope>
        </dependency>
    </dependencies>
</plugin>

<dependencies>
    <!-- all dependencies -->
    <!-- you can exclude rest-assured from spring-cloud-contract-verifier -->
    <dependency>
       <groupId>com.jayway.restassured</groupId>
       <artifactId>rest-assured</artifactId>
       <version>2.5.0</version>
       <scope>test</scope>
    </dependency>
    <dependency>
       <groupId>com.jayway.restassured</groupId>
       <artifactId>spring-mock-mvc</artifactId>
       <version>2.5.0</version>
       <scope>test</scope>
    </dependency>
</dependencies>

这样,插件会自动看到 Rest Assured 2.x 存在于 Classpath 中 并相应地修改导入。spring-doc.cadn.net.cn

使用 Maven 的快照版本和里程碑版本

要使用快照和里程碑版本,您必须将以下部分添加到pom.xml:spring-doc.cadn.net.cn

<repositories>
	<repository>
		<id>spring-snapshots</id>
		<name>Spring Snapshots</name>
		<url>https://repo.spring.io/snapshot</url>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
	</repository>
	<repository>
		<id>spring-milestones</id>
		<name>Spring Milestones</name>
		<url>https://repo.spring.io/milestone</url>
		<snapshots>
			<enabled>false</enabled>
		</snapshots>
	</repository>
</repositories>
<pluginRepositories>
	<pluginRepository>
		<id>spring-snapshots</id>
		<name>Spring Snapshots</name>
		<url>https://repo.spring.io/snapshot</url>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
	</pluginRepository>
	<pluginRepository>
		<id>spring-milestones</id>
		<name>Spring Milestones</name>
		<url>https://repo.spring.io/milestone</url>
		<snapshots>
			<enabled>false</enabled>
		</snapshots>
	</pluginRepository>
</pluginRepositories>

添加存根

默认情况下, Spring Cloud Contract Verifier 在src/test/resources/contracts目录。包含存根定义的目录为 被视为类名,并且每个存根定义都被视为单个测试。我们假设 它至少包含一个要用作测试类名的目录。如果还有更多 而不是一个级别的嵌套目录,则除最后一个目录外的所有目录都用作包名称。 请考虑以下结构:spring-doc.cadn.net.cn

src/test/resources/contracts/myservice/shouldCreateUser.groovy
src/test/resources/contracts/myservice/shouldReturnUser.groovy

给定该结构, Spring Cloud Contract Verifier 创建一个名为defaultBasePackage.MyService有两种方法:spring-doc.cadn.net.cn

运行插件

generateTestsplugin 目标被分配为在名为generate-test-sources.如果您希望它成为构建过程的一部分,则无需这样做 什么。如果您只想生成测试,请调用generateTests目标。spring-doc.cadn.net.cn

如果要从 Maven 运行存根,请调用rungoal 中,存根作为spring.cloud.contract.verifier.stubssystem 属性,如下所示:spring-doc.cadn.net.cn

mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:run \ -Dspring.cloud.contract.verifier.stubs=“com.acme:服务名称”spring-doc.cadn.net.cn

配置插件

要更改默认配置,您可以添加configuration部分添加到插件中 定义或execution定义,如下所示:spring-doc.cadn.net.cn

<plugin>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>convert</goal>
                <goal>generateStubs</goal>
                <goal>generateTests</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <basePackageForTests>org.springframework.cloud.verifier.twitter.place</basePackageForTests>
        <baseClassForTests>org.springframework.cloud.verifier.twitter.place.BaseMockMvcSpec</baseClassForTests>
    </configuration>
</plugin>

配置选项

  • testMode:定义验收测试的模式。默认情况下,模式为MockMvc, 它基于 Spring 的 MockMvc。您也可以将其更改为WebTestClient,JaxRsClientExplicit(对于真正的 HTTP 调用)。spring-doc.cadn.net.cn

  • basePackageForTests:指定所有生成的测试的基础包。如果未设置,则 该值是从baseClassForTests和 从packageWithBaseClasses. 如果这两个值均未设置,则该值将设置为org.springframework.cloud.contract.verifier.tests.spring-doc.cadn.net.cn

  • ruleClassForTests:指定应添加到生成的测试的规则 类。spring-doc.cadn.net.cn

  • baseClassForTests:为所有生成的测试创建一个基类。默认情况下,如果你 使用 Spock 类,则 class 为spock.lang.Specification.spring-doc.cadn.net.cn

  • contractsDirectory:指定一个目录,其中包含使用 Groovyn DSL.默认目录为/src/test/resources/contracts.spring-doc.cadn.net.cn

  • generatedTestSourcesDir:指定生成测试的测试源目录 应该放置 Groovy DSL。默认情况下,其值为$buildDir/generated-test-sources/contracts.spring-doc.cadn.net.cn

  • generatedTestResourcesDir:指定生成的测试使用的资源的测试资源目录。spring-doc.cadn.net.cn

  • testFramework:指定要使用的目标测试框架。目前,Spock、JUnit 4 (TestFramework.JUNIT) 和 支持 JUnit 5,其中 JUnit 4 是默认框架。spring-doc.cadn.net.cn

  • packageWithBaseClasses:定义所有基类所在的包。这 设置优先于baseClassForTests.约定是这样的,如果你 在 (例如) 下签订合同src/test/resources/contract/foo/bar/baz/并设置 的packageWithBaseClassesproperty 设置为com.example.baseSpring Cloud Contract Verifier 假定存在BarBazBasecom.example.base包。换句话说,系统采用 package(如果存在)并形成一个类Base作为后缀。spring-doc.cadn.net.cn

  • baseClassMappings:指定提供contractPackageRegex(根据 Contract 所在的软件包进行检查 located) 和baseClassFQN( 映射到 的基类的完全限定名称 匹配的合约)。例如,如果您在src/test/resources/contract/foo/bar/baz/并映射.* → com.example.base.BaseClassproperty,则从这些协定生成的测试类 延伸com.example.base.BaseClass.此设置优先于packageWithBaseClassesbaseClassForTests.spring-doc.cadn.net.cn

  • contractsProperties:包含要传递给 Spring Cloud Contract 的属性的 map 组件。这些属性可能由(例如)内置或自定义 Stub Downloader 使用。spring-doc.cadn.net.cn

  • failOnNoContracts:启用后,如果未找到 Contract,将引发异常。默认为true.spring-doc.cadn.net.cn

  • failOnInProgress:如果设置为true,然后,如果找到任何正在进行的合同,它们就会中断构建。在生产者方面,您需要明确说明您有正在进行的合同这一事实,并考虑到您可能会在消费者方面导致误报测试结果。默认为true.spring-doc.cadn.net.cn

  • incrementalContractTests:启用后,仅当自上次构建以来合同发生更改时,才会创建测试。默认为true.spring-doc.cadn.net.cn

  • incrementalContractStubs:启用后,仅当自上次构建以来合同发生更改时,才会创建存根。默认为true.spring-doc.cadn.net.cn

  • incrementalContractStubsJar:启用后,仅当存根自上次构建以来发生更改时,才会创建存根 jar。默认为true. *httpPort:提供存根的 WireMock 服务器的 HTTP 端口。现在spring.cloud.contract.verifier.http.port属性仅在从目录中提供存根时有效。否则,在提供存根 ID 时,必须在 id 字符串中包含 port。 *skip:将此项设置为true绕过验证程序执行。 *skipTestOnly:将此项设置为true绕过验证程序测试生成。 *stubs:要下载并以冒号分隔的 Ivy 表示法运行的存根列表。 *minPort:指定存根应从的最小端口开始。 *maxPort:指定存根应开始的最大端口。 *waitForKeyPressed:指定插件是否应在启动存根后等待用户按下该键。 *stubsClassifier:指定存根工件使用的分类器。spring-doc.cadn.net.cn

如果要从 Maven 存储库下载合同定义,可以使用 以下选项:spring-doc.cadn.net.cn

  • contractDependency:包含所有打包合同的合同依赖项。spring-doc.cadn.net.cn

  • contractsPath:具有打包合同的 JAR 中具体合同的路径。 默认为groupid/artifactid哪里gropuid是斜杠分隔的。spring-doc.cadn.net.cn

  • contractsMode:选择查找和注册存根的模式。spring-doc.cadn.net.cn

  • deleteStubsAfterTest:如果设置为false,请勿删除任何已下载的内容 来自临时目录的 Contract。spring-doc.cadn.net.cn

  • contractsRepositoryUrl:包含具有协定的构件的存储库的 URL。如果未提供, 使用当前的 Maven 的。spring-doc.cadn.net.cn

  • contractsRepositoryUsername:用于通过 Contract 连接到 repo 的用户名。spring-doc.cadn.net.cn

  • contractsRepositoryPassword:用于通过 Contract 连接到 repo 的密码。spring-doc.cadn.net.cn

  • contractsRepositoryProxyHost:用于通过 Contract 连接到 repo 的代理主机。spring-doc.cadn.net.cn

  • contractsRepositoryProxyPort:用于通过合约连接到仓库的代理端口。spring-doc.cadn.net.cn

我们只缓存非快照的、显式提供的版本(例如+1.0.0.BUILD-SNAPSHOT不要被缓存)。默认情况下,此功能处于打开状态。spring-doc.cadn.net.cn

以下列表描述了您可以在插件中打开的实验性功能:spring-doc.cadn.net.cn

  • convertToYaml:将所有 DSL 转换为声明式 YAML 格式。当您在 Groovy DSL 中使用外部库时,这可能非常有用。通过启用此功能(通过将其设置为true),则无需在使用者端添加库依赖项。spring-doc.cadn.net.cn

  • assertJsonSize:您可以在生成的测试中检查 JSON 数组的大小。默认情况下,此功能处于禁用状态。spring-doc.cadn.net.cn

所有测试的单个基类

当在默认 (MockMvc),您需要创建一个 base 规范。在此类中,您需要指向一个 endpoint,该端点应进行验证。以下示例显示了如何执行此作:spring-doc.cadn.net.cn

import org.mycompany.ExampleSpringController
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
import spock.lang.Specification

class MvcSpec extends Specification {
  def setup() {
   RestAssuredMockMvc.standaloneSetup(new ExampleSpringController())
  }
}

If necessary, you can also setup the whole context, as the following example shows:spring-doc.cadn.net.cn

import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SomeConfig.class, properties="some=property")
public abstract class BaseTestClass {

	@Autowired
	WebApplicationContext context;

	@Before
	public void setup() {
		RestAssuredMockMvc.webAppContextSetup(this.context);
	}
}

If you use EXPLICIT mode, you can use a base class to initialize the whole tested app, similar to what you might do in regular integration tests. The following example shows how to do so:spring-doc.cadn.net.cn

import io.restassured.RestAssured;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.web.context.WebApplicationContext;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SomeConfig.class, properties="some=property")
public abstract class BaseTestClass {

	@LocalServerPort
	int port;

	@Before
	public void setup() {
		RestAssured.baseURI = "http://localhost:" + this.port;
	}
}

If you use the JAXRSCLIENT mode, this base class should also contain a protected WebTarget webTarget field. Right now, the only way to test the JAX-RS API is to start a web server.spring-doc.cadn.net.cn

Using Different Base Classes for Contracts

If your base classes differ between contracts, you can tell the Spring Cloud Contract plugin which class should get extended by the autogenerated tests. You have two options:spring-doc.cadn.net.cn

By Convention

The convention is such that if you have a contract under (for example) src/test/resources/contract/foo/bar/baz/ and set the value of the packageWithBaseClasses property to com.example.base, then Spring Cloud Contract Verifier assumes that there is a BarBazBase class under the com.example.base package. In other words, the system takes the last two parts of the package, if they exist, and forms a class with a Base suffix. This rule takes precedence over baseClassForTests. The following example shows how it works in the contracts closure:spring-doc.cadn.net.cn

<plugin>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-maven-plugin</artifactId>
	<configuration>
		<packageWithBaseClasses>hello</packageWithBaseClasses>
	</configuration>
</plugin>

By Mapping

You can manually map a regular expression of the contract’s package to the fully qualified name of the base class for the matched contract. You have to provide a list called baseClassMappings that consists of baseClassMapping objects that each take a contractPackageRegex to baseClassFQN mapping. Consider the following example:spring-doc.cadn.net.cn

<plugin>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-maven-plugin</artifactId>
	<configuration>
		<baseClassForTests>com.example.FooBase</baseClassForTests>
		<baseClassMappings>
			<baseClassMapping>
				<contractPackageRegex>.*com.*</contractPackageRegex>
				<baseClassFQN>com.example.TestBase</baseClassFQN>
			</baseClassMapping>
		</baseClassMappings>
	</configuration>
</plugin>

Assume that you have contracts under these two locations:spring-doc.cadn.net.cn

By providing the baseClassForTests, we have a fallback in case mapping did not succeed. (You can also provide the packageWithBaseClasses as a fallback.) That way, the tests generated from src/test/resources/contract/com/ contracts extend the com.example.ComBase, whereas the rest of the tests extend com.example.FooBase.spring-doc.cadn.net.cn

Invoking Generated Tests

The Spring Cloud Contract Maven Plugin generates verification code in a directory called /generated-test-sources/contractVerifier and attaches this directory to testCompile goal.spring-doc.cadn.net.cn

For Groovy Spock code, you can use the following:spring-doc.cadn.net.cn

<plugin>
	<groupId>org.codehaus.gmavenplus</groupId>
	<artifactId>gmavenplus-plugin</artifactId>
	<version>1.5</version>
	<executions>
		<execution>
			<goals>
				<goal>testCompile</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/contractVerifier</directory>
				<includes>
					<include>**/*.groovy</include>
				</includes>
			</testSource>
		</testSources>
	</configuration>
</plugin>

To ensure that the provider side is compliant with defined contracts, you need to invoke mvn generateTest test.spring-doc.cadn.net.cn

Pushing Stubs to SCM

If you use the SCM (Source Control Management) repository to keep the contracts and stubs, you might want to automate the step of pushing stubs to the repository. To do that, you can add the pushStubsToScm goal. The following example shows how to do so:spring-doc.cadn.net.cn

<plugin>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <version>${spring-cloud-contract.version}</version>
    <extensions>true</extensions>
    <configuration>
        <!-- Base class mappings etc. -->

        <!-- We want to pick contracts from a Git repository -->
        <contractsRepositoryUrl>git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</contractsRepositoryUrl>

        <!-- We reuse the contract dependency section to set up the path
        to the folder that contains the contract definitions. In our case the
        path will be /groupId/artifactId/version/contracts -->
        <contractDependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>${project.artifactId}</artifactId>
            <version>${project.version}</version>
        </contractDependency>

        <!-- The contracts mode can't be classpath -->
        <contractsMode>REMOTE</contractsMode>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <!-- By default we will not push the stubs back to SCM,
                you have to explicitly add it as a goal -->
                <goal>pushStubsToScm</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Under Using the SCM Stub Downloader, you can find all possible configuration options that you can pass through the <configuration><contractsProperties> map, a system property, or an environment variable. For instance, you could specify a concrete branch to checkout, instead of the default onespring-doc.cadn.net.cn

<plugin>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
    <version>${spring-cloud-contract.version}</version>
    <extensions>true</extensions>
    <configuration>
        <!-- Base class mappings etc. -->

        <!-- We want to pick contracts from a Git repository -->
        <contractsRepositoryUrl>git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</contractsRepositoryUrl>
	<contractsProperties>
            <git.branch>another_branch</git.branch>
        </contractsProperties>

        <!-- We reuse the contract dependency section to set up the path
        to the folder that contains the contract definitions. In our case the
        path will be /groupId/artifactId/version/contracts -->
        <contractDependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>${project.artifactId}</artifactId>
            <version>${project.version}</version>
        </contractDependency>

        <!-- The contracts mode can't be classpath -->
        <contractsMode>REMOTE</contractsMode>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <!-- By default we will not push the stubs back to SCM,
                you have to explicitly add it as a goal -->
                <goal>pushStubsToScm</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Maven Plugin and STS

The following image shows an exception that you may see when you use STS:spring-doc.cadn.net.cn

STS Exception

When you click on the error marker, you should see something like the following:spring-doc.cadn.net.cn

 plugin:1.1.0.M1:convert:default-convert:process-test-resources) org.apache.maven.plugin.PluginExecutionException: Execution default-convert of goal org.springframework.cloud:spring-
 cloud-contract-maven-plugin:1.1.0.M1:convert failed. at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:145) at
 org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:331) at org.eclipse.m2e.core.internal.embedder.MavenImpl$11.call(MavenImpl.java:1362) at
...
 org.eclipse.core.internal.jobs.Worker.run(Worker.java:55) Caused by: java.lang.NullPointerException at
 org.eclipse.m2e.core.internal.builder.plexusbuildapi.EclipseIncrementalBuildContext.hasDelta(EclipseIncrementalBuildContext.java:53) at
 org.sonatype.plexus.build.incremental.ThreadBuildContext.hasDelta(ThreadBuildContext.java:59) at

To fix this issue, provide the following section in your pom.xml:spring-doc.cadn.net.cn

<build>
    <pluginManagement>
        <plugins>
            <!--This plugin's configuration is used to store Eclipse m2e settings
                only. It has no influence on the Maven build itself. -->
            <plugin>
                <groupId>org.eclipse.m2e</groupId>
                <artifactId>lifecycle-mapping</artifactId>
                <version>1.0.0</version>
                <configuration>
                    <lifecycleMappingMetadata>
                        <pluginExecutions>
                             <pluginExecution>
                                <pluginExecutionFilter>
                                    <groupId>org.springframework.cloud</groupId>
                                    <artifactId>spring-cloud-contract-maven-plugin</artifactId>
                                    <versionRange>[1.0,)</versionRange>
                                    <goals>
                                        <goal>convert</goal>
                                    </goals>
                                </pluginExecutionFilter>
                                <action>
                                    <execute />
                                </action>
                             </pluginExecution>
                        </pluginExecutions>
                    </lifecycleMappingMetadata>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

Maven Plugin with Spock Tests

You can select the Spock Framework for creating and running the auto-generated contract verification tests with both Maven and Gradle. However, while using Gradle is straightforward, in Maven, you need some additional setup in order to make the tests compile and execute properly.spring-doc.cadn.net.cn

First of all, you must use a plugin, such as the GMavenPlus plugin, to add Groovy to your project. In GMavenPlus plugin, you need to explicitly set test sources, including both the path where your base test classes are defined and the path were the generated contract tests are added. The following example shows how to do so.spring-doc.cadn.net.cn

If you uphold the Spock convention of ending the test class names with Spec, you also need to adjust your Maven Surefire plugin setup, as the following example shows.spring-doc.cadn.net.cn