消費者驅動合約,合約位於外部儲存庫中

在此流程中,我們執行消費者驅動合約測試。合約定義儲存在個別的儲存庫中。

先決條件

若要使用消費者驅動合約,並將合約保存在外部儲存庫中,您需要設定一個 Git 儲存庫,其

  • 包含每個生產者的所有合約定義。

  • 可以將合約定義打包在 JAR 中。

  • 對於每個合約生產者,都包含一種方式 (例如,pom.xml) 以透過 Spring Cloud Contract 外掛程式 (SCC 外掛程式) 在本地安裝 Stub。

如需更多資訊,請參閱操作指南章節,其中我們描述了如何設定此類儲存庫。如需此類專案的範例,請參閱此範例

您還需要設定了 Spring Cloud Contract Stub Runner 的消費者程式碼。如需此類專案的範例,請參閱此範例。您還需要設定了 Spring Cloud Contract 的生產者程式碼,以及一個外掛程式。如需此類專案的範例,請參閱此範例。Stub 儲存空間為 Nexus 或 Artifactory。

在高階層次,流程如下

  1. 消費者使用來自個別儲存庫的合約定義。

  2. 一旦消費者完成工作,就會在消費者端建立一個包含工作程式碼的分支,並向保存合約定義的個別儲存庫發出提取請求。

  3. 生產者接管對包含合約定義的個別儲存庫的提取請求,並在本地安裝包含所有合約的 JAR。

  4. 生產者從本地儲存的 JAR 產生測試,並編寫缺少的實作以使測試通過。

  5. 一旦生產者完成工作,對保存合約定義的儲存庫的提取請求就會合併。

  6. 在 CI 工具建置包含合約定義的儲存庫,並且包含合約定義的 JAR 上傳到 Nexus 或 Artifactory 之後,生產者可以合併其分支。

  7. 最後,消費者可以切換到線上工作,從遠端位置提取生產者的 Stub,並且分支可以合併到 master。

消費者流程

消費者

  1. 編寫一個會向生產者發送請求的測試。

    由於沒有伺服器,測試失敗。

  2. 複製保存合約定義的儲存庫。

  3. 將需求設定為資料夾下的合約,並以消費者名稱作為生產者的子資料夾。

    例如,對於名為 producer 的生產者和名為 consumer 的消費者,合約將儲存在 src/main/resources/contracts/producer/consumer/ 下)

  4. 一旦定義了合約,就將生產者 Stub 安裝到本地儲存空間,如下列範例所示

    $ cd src/main/resource/contracts/producer
    $ ./mvnw clean install
  5. 在消費者測試中設定 Spring Cloud Contract (SCC) Stub Runner,以

    • 從本地儲存空間提取生產者 Stub。

    • 在每個消費者的 Stub 模式下工作 (這會啟用消費者驅動合約模式)。

      SCC Stub Runner

    • 提取生產者 Stub。

    • 使用生產者 Stub 執行記憶體內 HTTP 伺服器 Stub。現在您的測試會與 HTTP 伺服器 Stub 通訊,並且您的測試通過。

    • 建立對包含合約定義的儲存庫的提取請求,其中包含生產者的新合約。

    • 分支您的消費者程式碼,直到生產者團隊合併他們的程式碼。

以下 UML 圖表顯示了消費者流程

flow-overview-consumer-cdc-external-consumer

生產者流程

生產者

  1. 接管對包含合約定義的儲存庫的提取請求。您可以從命令列執行此操作,如下所示

    $ git checkout -b the_branch_with_pull_request master
    git pull https://github.com/user_id/project_name.git the_branch_with_pull_request
  2. 安裝合約定義,如下所示

    $ ./mvnw clean install
  3. 設定外掛程式以從 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
    }

    ===

  4. 執行建置以產生測試和 Stub,如下所示

    === Maven:

    +

    ./mvnw clean install
    Gradle
    ./gradlew clean build

    ===

  5. 編寫缺少的實作,以使測試通過。

  6. 合併對包含合約定義的儲存庫的提取請求,如下所示

    $ 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。

  7. 切換到遠端工作。

  8. 設定外掛程式,以便不再從本地儲存空間而是從遠端位置取得合約定義,如下所示

    === 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
    }

    ===

  9. 合併具有新實作的生產者程式碼。

  10. CI 系統

    • 建置專案。

    • 產生測試、Stub 和 Stub JAR。

    • 將包含應用程式和 Stub 的成品上傳到 Nexus 或 Artifactory。

以下 UML 圖表顯示了生產者流程

flow-overview-consumer-cdc-external-producer