此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 spring-cloud-contract 4.1.5! |
Maven 项目
添加 Maven 插件
要添加 Spring Cloud Contract BOM,请在pom.xml
文件:
<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 Verifier
Maven 插件,如下所示:
<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>
您可以在 spring-cloud-contract-maven-plugin/index.html[Spring] Cloud Contract Maven Plugin 文档]。
有时,无论选择哪种 IDE,您都可以看到target/generated-test-source
文件夹在 IDE 的类路径中不可见。为确保它始终存在,您可以将以下条目添加到pom.xml
<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 Assured 2.x 将其添加到插件 Classpath 中,如下所示:
<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 中 并相应地修改导入。
使用 Maven 的快照版本和里程碑版本
要使用快照和里程碑版本,您必须将以下部分添加到pom.xml
:
<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
目录。包含存根定义的目录为
被视为类名,并且每个存根定义都被视为单个测试。我们假设
它至少包含一个要用作测试类名的目录。如果还有更多
而不是一个级别的嵌套目录,则除最后一个目录外的所有目录都用作包名称。
请考虑以下结构:
src/test/resources/contracts/myservice/shouldCreateUser.groovy
src/test/resources/contracts/myservice/shouldReturnUser.groovy
给定该结构, Spring Cloud Contract Verifier 创建一个名为defaultBasePackage.MyService
有两种方法:
-
shouldCreateUser()
-
shouldReturnUser()
运行插件
这generateTests
plugin 目标被分配为在名为generate-test-sources
.如果您希望它成为构建过程的一部分,则无需这样做
什么。如果您只想生成测试,请调用generateTests
目标。
如果要从 Maven 运行存根,请调用run
goal 中,存根作为spring.cloud.contract.verifier.stubs
system 属性,如下所示:
mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:run \ -Dspring.cloud.contract.verifier.stubs=“com.acme:服务名称”
配置插件
要更改默认配置,您可以添加configuration
部分添加到插件中
定义或execution
定义,如下所示:
<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
,JaxRsClient
或Explicit
(对于真正的 HTTP 调用)。 -
basePackageForTests
:指定所有生成的测试的基础包。如果未设置,则 该值是从baseClassForTests
和 从packageWithBaseClasses
. 如果这两个值均未设置,则该值将设置为org.springframework.cloud.contract.verifier.tests
. -
ruleClassForTests
:指定应添加到生成的测试的规则 类。 -
baseClassForTests
:为所有生成的测试创建一个基类。默认情况下,如果你 使用 Spock 类,则 class 为spock.lang.Specification
. -
contractsDirectory
:指定一个目录,其中包含使用 Groovyn DSL.默认目录为/src/test/resources/contracts
. -
generatedTestSourcesDir
:指定生成测试的测试源目录 应该放置 Groovy DSL。默认情况下,其值为$buildDir/generated-test-sources/contracts
. -
generatedTestResourcesDir
:指定生成的测试使用的资源的测试资源目录。 -
testFramework
:指定要使用的目标测试框架。目前,Spock、JUnit 4 (TestFramework.JUNIT
) 和 支持 JUnit 5,其中 JUnit 4 是默认框架。 -
packageWithBaseClasses
:定义所有基类所在的包。这 设置优先于baseClassForTests
.约定是这样的,如果你 在 (例如) 下签订合同src/test/resources/contract/foo/bar/baz/
并设置 的packageWithBaseClasses
property 设置为com.example.base
Spring Cloud Contract Verifier 假定存在BarBazBase
类com.example.base
包。换句话说,系统采用 package(如果存在)并形成一个类Base
作为后缀。 -
baseClassMappings
:指定提供contractPackageRegex
(根据 Contract 所在的软件包进行检查 located) 和baseClassFQN
( 映射到 的基类的完全限定名称 匹配的合约)。例如,如果您在src/test/resources/contract/foo/bar/baz/
并映射.* → com.example.base.BaseClass
property,则从这些协定生成的测试类 延伸com.example.base.BaseClass
.此设置优先于packageWithBaseClasses
和baseClassForTests
. -
contractsProperties
:包含要传递给 Spring Cloud Contract 的属性的 map 组件。这些属性可能由(例如)内置或自定义 Stub Downloader 使用。 -
failOnNoContracts
:启用后,如果未找到 Contract,将引发异常。默认为true
. -
failOnInProgress
:如果设置为true
,然后,如果找到任何正在进行的合同,它们就会中断构建。在生产者方面,您需要明确说明您有正在进行的合同这一事实,并考虑到您可能会在消费者方面导致误报测试结果。默认为true
. -
incrementalContractTests
:启用后,仅当自上次构建以来合同发生更改时,才会创建测试。默认为true
. -
incrementalContractStubs
:启用后,仅当自上次构建以来合同发生更改时,才会创建存根。默认为true
. -
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
:指定存根工件使用的分类器。
如果要从 Maven 存储库下载合同定义,可以使用 以下选项:
-
contractDependency
:包含所有打包合同的合同依赖项。 -
contractsPath
:具有打包合同的 JAR 中具体合同的路径。 默认为groupid/artifactid
哪里gropuid
是斜杠分隔的。 -
contractsMode
:选择查找和注册存根的模式。 -
deleteStubsAfterTest
:如果设置为false
,请勿删除任何已下载的内容 来自临时目录的 Contract。 -
contractsRepositoryUrl
:包含具有协定的构件的存储库的 URL。如果未提供, 使用当前的 Maven 的。 -
contractsRepositoryUsername
:用于通过 Contract 连接到 repo 的用户名。 -
contractsRepositoryPassword
:用于通过 Contract 连接到 repo 的密码。 -
contractsRepositoryProxyHost
:用于通过 Contract 连接到 repo 的代理主机。 -
contractsRepositoryProxyPort
:用于通过合约连接到仓库的代理端口。
我们只缓存非快照的、显式提供的版本(例如+
1.0.0.BUILD-SNAPSHOT
不要被缓存)。默认情况下,此功能处于打开状态。
以下列表描述了您可以在插件中打开的实验性功能:
-
convertToYaml
:将所有 DSL 转换为声明式 YAML 格式。当您在 Groovy DSL 中使用外部库时,这可能非常有用。通过启用此功能(通过将其设置为true
),则无需在使用者端添加库依赖项。 -
assertJsonSize
:您可以在生成的测试中检查 JSON 数组的大小。默认情况下,此功能处于禁用状态。
所有测试的单个基类
当在默认 (MockMvc
),您需要创建一个 base
规范。在此类中,您需要指向一个
endpoint,该端点应进行验证。以下示例显示了如何执行此作:
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())
}
}
如有必要,您还可以设置整个上下文,如下例所示:
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
mode 中,你可以使用基类来初始化整个测试的应用程序。
类似于您在常规集成测试中可能执行的作。以下示例显示了
如何作:
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.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 {
@LocalServerPort
int port;
@Before
public void setup() {
RestAssured.baseURI = "http://localhost:" + this.port;
}
}
如果您使用JAXRSCLIENT
mode 时,此基类还应包含一个protected WebTarget webTarget
田。右
现在,测试 JAX-RS API 的唯一方法是启动 Web 服务器。
对 Contract 使用不同的基类
如果您的基类在 Contract 之间不同,则可以告诉 Spring Cloud Contract plugin 哪个类应该由自动生成的测试进行扩展。您有两个选项:
-
遵循约定,为
packageWithBaseClasses
-
提供显式映射
baseClassMappings
按约定
约定是这样的,如果您在 (例如)src/test/resources/contract/foo/bar/baz/
并设置packageWithBaseClasses
property 设置为com.example.base
,然后是 Spring Cloud Contract
验证程序假定存在BarBazBase
类com.example.base
包。
换句话说,系统采用包的最后两部分(如果存在),并且
形成一个类,其中包含Base
后缀。此规则优先于baseClassForTests
.
以下示例显示了它在contracts
关闭:
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<packageWithBaseClasses>hello</packageWithBaseClasses>
</configuration>
</plugin>
按映射
您可以手动将 Contract 包的正则表达式映射到完全限定的
匹配合约的基类名称。您必须提供一个名为baseClassMappings
包括baseClassMapping
对象,每个对象都采用contractPackageRegex
自baseClassFQN
映射。请考虑以下示例:
<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>
假设您在以下两个位置签订了合同:
-
src/test/resources/contract/com/
-
src/test/resources/contract/foo/
通过提供baseClassForTests
,如果映射未成功,我们有一个回退。
(您还可以提供packageWithBaseClasses
作为后备。这样,测试
生成自src/test/resources/contract/com/
合约扩展了com.example.ComBase
,而其余测试扩展com.example.FooBase
.
调用生成的测试
Spring Cloud Contract Maven Plugin 在名为/generated-test-sources/contractVerifier
并将此目录附加到testCompile
目标。
对于 Groovy Spock 代码,您可以使用以下内容:
<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>
为了确保 provider 端符合定义的 Contract,您需要调用mvn generateTest test
.
将存根推送到 SCM
如果您使用 SCM (Source Control Management) 存储库来保存合同和
stubs 中,您可能希望自动执行将 stub 推送到
存储库。为此,您可以添加pushStubsToScm
目标。以下示例显示了如何执行此作:
<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>
在 Using the SCM Stub Downloader 下,您可以找到所有可能的
您可以传递的配置选项
这<configuration><contractsProperties>
map、系统属性、
或环境变量。例如,您可以指定要签出的具体分支,而不是默认分支
<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 时可能会看到的异常:

当您单击错误标记时,您应该会看到如下所示的内容:
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
:
<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 Framework 来创建和运行自动生成的合约 使用 Maven 和 Gradle 进行验证测试。但是,虽然使用 Gradle 很简单, 在 Maven 中,您需要一些额外的设置才能使测试正确编译和执行。
首先,您必须使用插件,例如 GMavenPlus 插件, 将 Groovy 添加到您的项目中。在 GMavenPlus 插件中,您需要显式设置测试源,包括 path 来定义您的基本测试类,并且 path 是添加生成的 Contract 测试的。 以下示例说明如何执行此作。
如果您坚持 Spock 约定,即以Spec
,您还需要调整您的 Maven
Surefire 插件设置,如下例所示。