对于最新的稳定版本,请使用 spring-cloud-contract 4.3.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 和 Assured 2.0

默认情况下,Rest Assured 3.x 被添加到类路径中。但是,您可以使用 Rest 通过将 2.x 添加到插件类路径来保证 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 存在于类路径上 并相应地修改导入。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

运行插件(Run Plugin)

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

如果您想从 Maven 运行存根,请调用run目标,存根作为spring.cloud.contract.verifier.stubs系统属性如下:spring-doc.cadn.net.cn

mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:运行 \ -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:为所有生成的测试创建一个基类。默认情况下,如果您 use Spock 类,则类是spock.lang.Specification.spring-doc.cadn.net.cn

  • contractsDirectory:指定一个目录,其中包含使用 格鲁文 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/并设置 的值packageWithBaseClasses属性设置为com.example.baseSpring 云合约验证程序假定存在BarBazBase类在com.example.base包。换句话说,系统采用 package(如果存在),并形成一个类Base作为后缀。spring-doc.cadn.net.cn

  • baseClassMappings:指定提供contractPackageRegex(根据合同所在的包进行检查 位于)和baseClassFQN( 映射到 匹配的合约)。例如,如果您有一份合同src/test/resources/contract/foo/bar/baz/并映射.* → com.example.base.BaseClass属性,从这些合约生成的测试类 延伸com.example.base.BaseClass.此设置优先于packageWithBaseClassesbaseClassForTests.spring-doc.cadn.net.cn

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

  • failOnNoContracts:启用后,将在未找到合约时抛出异常。默认为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 字符串中。 *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,请勿删除任何已下载的 临时目录中的合同。spring-doc.cadn.net.cn

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

  • contractsRepositoryUsername:用于连接到具有合约的存储库的用户名。spring-doc.cadn.net.cn

  • contractsRepositoryPassword:用于连接到具有合约的存储库的密码。spring-doc.cadn.net.cn

  • contractsRepositoryProxyHost:用于连接到具有合约的存储库的代理主机。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),您需要创建一个底座 所有生成的验收测试的规范。在本类中,您需要指向一个 端点,应进行验证。以下示例显示了如何执行此作: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())
  }
}

如有必要,您还可以设置整个上下文,如以下示例所示: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);
	}
}

如果您使用EXPLICIT模式,您可以使用基类来初始化整个测试的应用程序, 类似于您在常规集成测试中可能执行的作。以下示例显示 如何做到这一点: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;
	}
}

如果您使用JAXRSCLIENT模式,则此基类还应包含一个protected WebTarget webTarget田。右 现在,测试 JAX-RS API 的唯一方法是启动 Web 服务器。spring-doc.cadn.net.cn

对合约使用不同的基类

如果您的基类在合约之间不同,您可以告诉 Spring Cloud Contract插件应该通过自动生成的测试扩展哪个类。您有两个选择:spring-doc.cadn.net.cn

按惯例

约定是这样的,如果您根据(例如)src/test/resources/contract/foo/bar/baz/并将packageWithBaseClasses属性设置为com.example.base,然后是 Spring Cloud Contract 验证器假定有一个BarBazBase类在com.example.base包。 换句话说,系统会获取包的最后两个部分(如果存在),并且 使用Base后缀。此规则优先于baseClassForTests. 以下示例显示了它在contracts关闭:spring-doc.cadn.net.cn

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

通过映射

您可以手动将合约包的正则表达式映射到完全限定的 匹配协定的基类的名称。您必须提供一个名为baseClassMappings包括baseClassMapping每个对象都采用contractPackageRegexbaseClassFQN映射。请考虑以下示例: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>

假设您在这两个位置下有合同:spring-doc.cadn.net.cn

通过提供baseClassForTests,我们有一个后备,以防映射不成功。 (您还可以提供packageWithBaseClasses作为后备。这样,测试 生成自src/test/resources/contract/com/合约将com.example.ComBase,而其余测试则扩展com.example.FooBase.spring-doc.cadn.net.cn

调用生成的测试

Spring Cloud Contract Maven 插件在名为/generated-test-sources/contractVerifier并将此目录附加到testCompile目标。spring-doc.cadn.net.cn

对于 Groovy Spock 代码,您可以使用以下内容: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>

为了确保提供程序端符合定义的协定,您需要调用mvn generateTest test.spring-doc.cadn.net.cn

将存根推送到 SCM

如果您使用 SCM(源代码管理管理)存储库来保留合同和 存根,您可能希望自动执行将存根推送到 存储库。为此,您可以添加pushStubsToScm目标。以下示例显示了如何执行此作: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>

使用 SCM 存根下载器下,您可以找到所有可能的 您可以传递的配置选项 这<configuration><contractsProperties>map,一个系统属性, 或环境变量。例如,您可以指定要检出的具体分支,而不是默认分支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>
	<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 插件和 STS

下图显示了使用 STS 时可能会看到的异常:spring-doc.cadn.net.cn

STS Exception

单击错误标记时,您应该会看到如下内容: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

要解决此问题,请在您的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>

带有 Spock 测试的 Maven 插件

您可以选择 Spock 框架来创建和运行自动生成的合约 使用 Maven 和 Gradle 进行验证测试。但是,虽然使用 Gradle 很简单, 在 Maven 中,您需要一些额外的设置才能使测试正确编译和执行。spring-doc.cadn.net.cn

首先,您必须使用一个插件,例如 GMavenPlus 插件, 将 Groovy 添加到您的项目中。在 GMavenPlus 插件中,您需要显式设置测试源,包括 定义基本测试类的路径,添加生成的协定测试的路径。 以下示例演示了如何执行此作。spring-doc.cadn.net.cn

如果您坚持 Spock 约定,即测试类名称以Spec,您还需要调整您的 Maven Surefire 插件设置,如下示例所示。spring-doc.cadn.net.cn