使用外部仓库中的合约实现消费者驱动契约
在此流程中,我们执行消费者驱动契约测试。契约定义存储在单独的代码仓库中。
前提条件
要使用外部仓库中的消费者驱动契约,你需要设置一个git仓库,该仓库:
-
包含每个生产者的所有合约定义。
-
可以将合约定义打包成JAR文件。
-
对于每个合约生产者,都提供了一种方式(例如,
pom.xml),通过Spring Cloud Contract插件(SCC插件)在本地安装存根。
从高层次来看,流程如下:
-
消费者使用来自独立代码库的契约定义进行开发。
-
消费者完成工作后,会在消费者端创建一个包含可运行代码的分支,并向存放契约定义的独立代码库发起拉取请求。
-
生产者接手针对存放契约定义的独立代码库的拉取请求,并在本地安装包含所有契约的 JAR 包。
-
生产者根据本地存储的 JAR 包生成测试,并编写缺失的实现以使测试通过。
-
生产者完成工作后,将针对存放契约定义的代码库的拉取请求合并。
-
在 CI 工具构建包含契约定义的代码库,并将包含契约定义的 JAR 包上传至 Nexus 或 Artifactory 后,生产者可以合并其分支。
-
最后,消费者可以切换到在线工作模式,从远程位置获取生产者的存根,并将分支合并到主分支。
消费者流程
消费者:
-
编写一个向生产者发送请求的测试。
由于没有服务器存在,测试失败。
-
克隆包含契约定义的代码仓库。
-
将需求设置为文件夹下的契约,以消费者名称作为生产者的子文件夹。
例如,对于名为
producer的生产者和名为consumer的消费者,契约将存储在src/main/resources/contracts/producer/consumer/下。 -
一旦定义了契约,将生产者存根安装到本地存储,如下例所示:
$ cd src/main/resource/contracts/producer
$ ./mvnw clean install -
在消费者测试中设置 Spring Cloud Contract (SCC) Stub Runner,以:
-
从本地存储获取生产者存根。
-
在按消费者存根模式下工作(这启用了消费者驱动契约模式)。
SCC Stub Runner:
-
获取生产者存根。
-
使用生产者存根运行一个内存中的 HTTP 服务器存根。现在你的测试与 HTTP 服务器存根通信,并且你的测试通过。
-
向包含契约定义的代码仓库创建一个拉取请求,其中包含生产者的新契约。
-
分支你的消费者代码,直到生产者团队合并了他们的代码。
-
以下UML图展示了消费者流程:

生产者流程
生产者:
-
接管包含合约定义仓库的拉取请求。你可以通过命令行操作,如下所示:
$ git checkout -b the_branch_with_pull_request master
git pull https://github.com/user_id/project_name.git the_branch_with_pull_request -
安装合约定义,如下所示:
$ ./mvnw clean install -
设置插件以从 JAR 中获取合约定义,而不是从
src/test/resources/contracts中获取,如下所示:Maven
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<!-- 我们希望使用具有以下坐标的包含合约的 JAR -->
<contractDependency>
<groupId>com.example</groupId>
<artifactId>beer-contracts</artifactId>
</contractDependency>
<!-- 包含合约的 JAR 应从本地 Maven 仓库获取 -->
<contractsMode>LOCAL</contractsMode>
<!-- ... 其他配置 -->
</configuration>
</plugin>Gradle
contracts {
// 我们希望使用具有以下坐标的包含合约的 JAR
// group id `com.example`, artifact id `beer-contracts`, 最新版本且无分类器
contractDependency {
stringNotation = 'com.example:beer-contracts:+:'
}
// 包含合约的 JAR 应从本地 Maven 仓库获取
contractsMode = "LOCAL"
// 其他配置
} -
运行构建以生成测试和存根,如下所示:
Maven
./mvnw clean installGradle
./gradlew clean build -
编写缺失的实现,以使测试通过。
-
将拉取请求合并到包含合约定义的仓库中,如下所示:
$ git commit -am "Finished the implementation to make the contract tests pass"
$ git checkout master
$ git merge --no-ff the_branch_with_pull_request
$ git push origin masterCI 系统会构建包含合约定义的项目,并将包含合约定义的 JAR 上传到 Nexus 或 Artifactory。
-
切换到远程工作模式。
-
设置插件,使合约定义不再从本地存储获取,而是从远程位置获取,如下所示:
Maven
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<!-- 我们希望使用具有以下坐标的包含合约的 JAR -->
<contractDependency>
<groupId>com.example</groupId>
<artifactId>beer-contracts</artifactId>
</contractDependency>
<!-- 包含合约的 JAR 应从远程位置获取 -->
<contractsMode>REMOTE</contractsMode>
<!-- ... 其他配置 -->
</configuration>
</plugin>Gradle
contracts {
// 我们希望使用具有以下坐标的包含合约的 JAR
// group id `com.example`, artifact id `beer-contracts`, 最新版本且无分类器
contractDependency {
stringNotation = 'com.example:beer-contracts:+:'
}
// 包含合约的 JAR 应从远程位置获取
contractsMode = "REMOTE"
// 其他配置
} -
将生产者代码与新的实现合并。
-
CI 系统:
-
构建项目。
-
生成测试、存根以及存根 JAR。
-
将包含应用程序和存根的构件上传到 Nexus 或 Artifactory。
下面的UML图展示了生产者进程:
