消费者驱动契约,契约存放在外部仓库中
在此流程中,我们执行消费者驱动契约测试。契约定义存储在单独的仓库中。
前置条件
要使用消费者驱动的契约(consumer-driven contracts),并将契约存储在外部仓库中,您需要设置一个 Git 仓库,其内容如下:
-
包含每个生产者的所有契约定义。
-
可以将契约定义打包到 JAR 文件中。
-
对于每个合同生产者,都包含一种方式(例如
pom.xml)通过 Spring Cloud Contract 插件(SCC 插件)本地安装存根。
您还需要配置了 Spring Cloud Contract Stub Runner 的消费者代码。有关此类项目的示例,请参见 此示例。您还需要配置了 Spring Cloud Contract 以及插件的生产者代码。有关此类项目的示例,请参见 此示例。存根存储使用的是 Nexus 或 Artifactory。
从高层角度来看,流程如下:
-
消费者与独立仓库中的契约定义进行协作。
-
当消费者的工作完成后,会在消费者端创建一个包含工作代码的分支,并向存放契约定义的独立仓库提交拉取请求。
-
生产者接管拉取请求,将其提交到包含契约定义的独立仓库,并将包含所有契约的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 框架 插件 运行器:
-
获取生产者存根。
-
Runs an in-memory HTTP server stub with the producer stubs. Now your test communicates with the HTTP server stub, and your tests pass.
-
创建一个拉取请求,提交到包含协议定义仓库中,用于生产者的新协议。
-
分支您的消费者代码,直到生产者团队合并其代码。
-
下图显示了以下 UML 图中显示的消费流:
生产者流程
The producer:
-
接管具有合同定义的仓库的拉取请求。你可以从命令行进行,如下所示
$ 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> <!-- We want to use the JAR with contracts with the following coordinates --> <contractDependency> <groupId>com.example</groupId> <artifactId>beer-contracts</artifactId> </contractDependency> <!-- The JAR with contracts should be taken from Maven local --> <contractsMode>LOCAL</contractsMode> <!-- ... additional configuration --> </configuration> </plugin> - Gradle
-
contracts { // We want to use the JAR with contracts with the following coordinates // group id `com.example`, artifact id `beer-contracts`, LATEST version and NO classifier contractDependency { stringNotation = 'com.example:beer-contracts:+:' } // The JAR with contracts should be taken from Maven local contractsMode = "LOCAL" // Additional configuration }
-
运行构建以生成测试和占位代码,如下:
- Maven
-
./mvnw clean install - Gradle
-
./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> <!-- We want to use the JAR with contracts with the following coordinates --> <contractDependency> <groupId>com.example</groupId> <artifactId>beer-contracts</artifactId> </contractDependency> <!-- The JAR with contracts should be taken from a remote location --> <contractsMode>REMOTE</contractsMode> <!-- ... additional configuration --> </configuration> </plugin> - Gradle
-
contracts { // We want to use the JAR with contracts with the following coordinates // group id `com.example`, artifact id `beer-contracts`, LATEST version and NO classifier contractDependency { stringNotation = 'com.example:beer-contracts:+:' } // The JAR with contracts should be taken from a remote location contractsMode = "REMOTE" // Additional configuration }
-
将生产者代码与新实现合并。
-
系统是:
-
构建项目。
-
生成测试、存根和存根 JAR。
-
将应用程序和存根 artifacts 上传到 Nexus 或 Artifactory。
-
下面的UML图显示了生产者过程: