基於外部倉庫契約的消費者驅動契約
在這個流程中,我們執行消費者驅動契約測試。契約定義儲存在一個獨立的倉庫中。
先決條件
要使用基於外部倉庫契約的消費者驅動契約,你需要設定一個 Git 倉庫,該倉庫需要:
-
包含每個生產者的所有契約定義。
-
能夠將契約定義打包成 JAR。
-
對於每個契約生產者,包含一種方式(例如
pom.xml
)透過 Spring Cloud Contract 外掛 (SCC Plugin) 在本地安裝存根。
你還需要設定了 Spring Cloud Contract Stub Runner 的消費者程式碼。此類專案的示例請參閱這個示例。你還需要設定了 Spring Cloud Contract 和其外掛的生產者程式碼。此類專案的示例請參閱這個示例。存根儲存可以是 Nexus 或 Artifactory。
概括而言,流程如下:
-
消費者使用來自獨立倉庫的契約定義進行工作。
-
消費者工作完成後,在消費者側建立一個包含工作程式碼的分支,並向儲存契約定義的獨立倉庫提交一個 pull request。
-
生產者接管向儲存契約定義的獨立倉庫提交的 pull request,並在本地安裝包含所有契約的 JAR。
-
生產者從本地儲存的 JAR 生成測試,並編寫缺失的實現程式碼以使測試透過。
-
生產者工作完成後,合併向儲存契約定義的倉庫提交的 pull request。
-
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,以便:
-
從本地儲存獲取生產者存根。
-
在 stubs-per-consumer 模式下工作(這啟用消費者驅動契約模式)。
SCC Stub Runner 會:
-
獲取生產者存根。
-
執行一個包含生產者存根的記憶體中 HTTP 伺服器存根。現在你的測試與 HTTP 伺服器存根通訊,並且你的測試透過。
-
向儲存契約定義的倉庫建立一個包含生產者新契約的 pull request。
-
分支你的消費者程式碼,直到生產者團隊合併他們的程式碼。
-
以下 UML 圖顯示了消費者流程:

生產者流程
生產者:
-
接管向儲存契約定義的倉庫提交的 pull request。你可以從命令列執行此操作,如下所示:
$ 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
-
編寫缺失的實現程式碼,以使測試透過。
-
合併向儲存契約定義的倉庫提交的 pull request,如下所示:
$ 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 master
CI 系統構建包含契約定義的專案,並將包含契約定義的 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 }
-
合併包含新實現的生產者程式碼。
-
CI 系統會:
-
構建專案。
-
生成測試、存根和存根 JAR。
-
將包含應用程式和存根的 artifact 上傳到 Nexus 或 Artifactory。
-
以下 UML 圖顯示了生產者流程:
