此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 spring-cloud-contract 4.2.1

包含生产者端合同的消费者驱动型合同 (CDC) 分步指南

考虑欺诈检测和贷款发放流程的示例。业务 情况是这样的,我们想向人们发放贷款,但不希望他们从 我们。我们系统的当前实施向所有人提供贷款。

假设Loan IssuanceFraud Detection服务器。在当前的 sprint,我们必须开发一个新功能:如果客户想借太多钱, 我们将客户标记为欺诈者。

服务器端代码位于 Spring Cloud Contract Samples 存储库下samples/standalone/dsl/http-server路径,客户端代码位于 Spring Cloud Contract 的存储库下samples/standalone/dsl/http-client路径。

在这种情况下,生产商拥有合同。从物理上讲,所有的合同都是 在生产者的存储库中。

技术说明

重要提示:所有代码都可以在 spring Cloud Contract Samples repo 下找到。

为简单起见,我们使用以下首字母缩略词:

消费者方面(贷款发放)

作为 Loan Issuance 服务的开发人员(Fraud Detection 服务器的使用者),您可以执行以下步骤:

  1. 通过为您的功能编写测试来开始执行 TDD。

  2. 编写缺少的实现。

  3. 在本地克隆 Fraud Detection 服务存储库。

  4. 在欺诈检测服务的存储库中本地定义合同。

  5. 添加 Spring Cloud Contract (SCC) 插件。

  6. 运行集成测试。

  7. 提交拉取请求。

  8. 创建初始实施。

  9. 接管拉取请求。

  10. 编写缺少的实现。

  11. 部署您的应用程序。

  12. 在线工作。

我们从贷款发放流程开始,下面的 UML 图显示了该流程:

获取启动的 cdc 客户端

通过为您的功能编写测试来开始执行 TDD

下面的清单显示了一个测试,我们可能使用它来检查贷款金额是否太过 大:

假设您已经编写了新功能的测试。如果贷款申请为大 收到金额后,系统应拒绝该贷款申请,并提供一些说明。

编写缺失的实现

在某个时间点,您需要向 Fraud Detection 服务发送请求。假设 您需要发送包含客户端 ID 和金额的请求 客户想借钱。您希望将其发送到/fraudcheckURL 使用PUT方法。 为此,您可以使用类似于以下内容的代码:

为简单起见,Fraud Detection 服务的端口设置为8080和 应用程序在8090.

如果此时启动测试,它将中断,因为当前没有服务在 port 上运行8080.

在本地克隆 Fraud Detection 服务存储库

你可以从玩弄服务器端合约开始。为此,您必须首先 通过运行以下命令克隆它:

$ git clone https://your-git-server.com/server-side.git local-http-server-repo

在 Fraud Detection Service 的存储库中本地定义合同

作为消费者,您需要定义您到底想要实现的目标。您需要制定 您的期望。为此,请编写以下 contract:

将合约放在src/test/resources/contracts/fraud文件夹。这fraud文件夹 很重要,因为生成者的测试基类名称引用该文件夹。

以下示例显示了我们在 Groovy 和 YAML 中的合约:

YML 合约非常简单。但是,当您查看合同时 使用静态类型的 Groovy DSL 编写,您可能想知道value(client(…​), server(…​))零件是。通过使用此表示法,Spring Cloud Contract 允许您定义 JSON 块、URL 或其他动态结构的各个部分。在这种情况下 的标识符或时间戳,则无需对值进行硬编码。您希望允许一些 不同的值范围。要启用值范围,您可以设置正则表达式 与使用者端的这些值匹配。您可以通过以下方式提供正文 映射表示法或带有插值的 String。我们强烈建议使用 map 表示法。

要设置合约,您必须了解 map 表示法。请参阅有关 JSON 的 Groovy 文档

前面显示的合同是双方之间的协议,该协议:

准备好在集成测试中实际检查 API 后,您需要 在本地安装存根。

添加 Spring Cloud Contract Verifier 插件

我们可以添加 Maven 或 Gradle 插件。在此示例中,我们将展示如何添加 Maven。 首先,我们将Spring Cloud ContractBOM,如下例所示:

接下来,添加Spring Cloud Contract VerifierMaven 插件,如下例所示:

由于添加了插件,因此您将获得Spring Cloud Contract Verifier功能,其中, 从提供的 Contract 中:

您不想生成测试,因为您作为使用者只想使用 存根。您需要跳过测试生成和调用。为此,请运行以下命令:

$ cd local-http-server-repo
$ ./mvnw clean install -DskipTests

运行这些命令后,您应该会在日志中看到类似以下内容的内容:

[INFO] --- spring-cloud-contract-maven-plugin:1.0.0.BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
[INFO] Building jar: /some/path/http-server/target/http-server-0.0.1-SNAPSHOT-stubs.jar
[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ http-server ---
[INFO] Building jar: /some/path/http-server/target/http-server-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:1.5.5.BUILD-SNAPSHOT:repackage (default) @ http-server ---
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ http-server ---
[INFO] Installing /some/path/http-server/target/http-server-0.0.1-SNAPSHOT.jar to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT.jar
[INFO] Installing /some/path/http-server/pom.xml to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT.pom
[INFO] Installing /some/path/http-server/target/http-server-0.0.1-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar

以下行非常重要:

[INFO] Installing /some/path/http-server/target/http-server-0.0.1-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar

它确认了http-server已安装在本地 存储 库。

运行集成测试

为了从 Spring Cloud Contract Stub Runner 的自动 stub 下载,您必须在使用者端项目 (Loan Application service):

  1. 添加Spring Cloud ContractBOM 中,如下所示:

  2. 将依赖项添加到Spring Cloud Contract Stub Runner如下:

  3. 使用@AutoConfigureStubRunner.在注释中,提供group-idartifact-id供 Stub Runner 下载您的 合作。

  4. (可选)由于您正在离线与协作者一起玩游戏,因此您 还可以提供离线工作开关 (StubRunnerProperties.StubsMode.LOCAL).

现在,当您运行测试时,您会在日志中看到类似于以下输出的内容:

2016-07-19 14:22:25.403  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is + - will try to resolve the latest version
2016-07-19 14:22:25.438  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is 0.0.1-SNAPSHOT
2016-07-19 14:22:25.439  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact com.example:http-server:jar:stubs:0.0.1-SNAPSHOT using remote repositories []
2016-07-19 14:22:25.451  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved artifact com.example:http-server:jar:stubs:0.0.1-SNAPSHOT to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar
2016-07-19 14:22:25.465  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacking stub from JAR [URI: file:/path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar]
2016-07-19 14:22:25.475  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacked file to [/var/folders/0p/xwq47sq106x1_g3dtv6qfm940000gq/T/contracts100276532569594265]
2016-07-19 14:22:27.737  INFO 41050 --- [           main] o.s.c.c.stubrunner.StubRunnerExecutor    : All stubs are now running RunningStubs [namesAndPorts={com.example:http-server:0.0.1-SNAPSHOT:stubs=8080}]

此输出意味着 Stub Runner 已找到您的存根并为您的应用程序启动了一个服务器 组 ID 为com.example工件 ID 为http-server带版本0.0.1-SNAPSHOT之 存根和stubs端口上的分类器8080.

提交 Pull Request

到目前为止,您所做的是一个迭代过程。你可以尝试使用 Contract 中,将其安装在本地,并在 Consumer 端工作,直到 Contract 像 你希望。

对结果和测试通过感到满意后,您可以将拉取请求发布到 服务器端。目前,消费者端的工作已经完成。

生产者端(欺诈检测服务器)

作为 Fraud Detection 服务器(贷款发放服务的服务器)的开发人员,您 可能想要:

以下 UML 图显示了欺诈检测流程:

获取启动的 cdc 服务器

接管 Pull Request

提醒一下,下面的清单显示了初始实现:

然后,您可以运行以下命令:

$ git checkout -b contract-change-pr master
$ git pull https://your-git-server.com/server-side-fork.git contract-change-pr

您必须添加自动生成的测试所需的依赖项,如下所示:

在 Maven 插件的配置中,必须将packageWithBaseClasses属性,如下所示:

此示例使用“基于约定”的命名,方法是将packageWithBaseClasses财产。这样做意味着最后两个包合并为 make 基测试类的名称。在我们的例子中,合同被放在src/test/resources/contracts/fraud.由于您没有两个从 这contracts文件夹中,只选择一个,它应该是fraud.添加Basesuffix 和 利用fraud.这样,你就可以得到FraudBasetest 类名称。

所有生成的测试都扩展了该类。在那里,你可以设置你的 Spring Context 或任何必要的。在这种情况下,您应该使用 Rest Assured MVC 来 启动服务器端FraudDetectionController.下面的清单显示了FraudBase类:

现在,如果您运行./mvnw clean install,您会得到类似于以下输出的内容:

Results :

Tests in error:
  ContractVerifierTest.validate_shouldMarkClientAsFraud:32 » IllegalState Parsed...

发生此错误的原因是您有一个生成测试的新合同,并且它 失败,因为您尚未实现该功能。自动生成的测试将看起来 类似于以下测试方法:

@Test
public void validate_shouldMarkClientAsFraud() throws Exception {
    // given:
        MockMvcRequestSpecification request = given()
                .header("Content-Type", "application/vnd.fraud.v1+json")
                .body("{\"client.id\":\"1234567890\",\"loanAmount\":99999}");

    // when:
        ResponseOptions response = given().spec(request)
                .put("/fraudcheck");

    // then:
        assertThat(response.statusCode()).isEqualTo(200);
        assertThat(response.header("Content-Type")).matches("application/vnd.fraud.v1.json.*");
    // and:
        DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
        assertThatJson(parsedJson).field("['fraudCheckStatus']").matches("[A-Z]{5}");
        assertThatJson(parsedJson).field("['rejection.reason']").isEqualTo("Amount too high");
}

如果你使用过 Groovy DSL,你可以看到所有producer()合约中存在于value(consumer(…​), producer(…​))blocks 被注入到测试中。 如果您使用 YAML,则这同样适用于matchers部分的response.

请注意,在生产者端,您也在执行 TDD。期望被表达出来 以测试的形式。此测试向我们自己的应用程序发送一个请求,其中包含 URL headers 和 body 中定义的 Body。它还需要精确定义的值 在响应中。换句话说,您拥有red部分red,greenrefactor.是时候转换redgreen.

编写缺失的实现

因为您知道预期的输入和预期的输出,所以您可以编写缺失的 实现如下:

当您运行./mvnw clean install同样,测试通过。由于 Spring Cloud Contract Verifier 插件将测试添加到generated-test-sources您可以 实际从 IDE 运行这些测试。

部署应用程序

完成工作后,您可以部署更改。为此,您必须首先合并 branch 来运行以下命令:

$ git checkout master
$ git merge --no-ff contract-change-pr
$ git push origin master

您的 CI 可能会运行如下命令./mvnw clean deploy,这将发布 application 和 stub 工件。

消费者方(贷款发放),最后一步

作为贷款发放服务的开发人员(Fraud Detection 服务器的使用者),您需要:

下面的 UML 图显示了进程的最终状态:

获取启动项 CDC 客户端最终

将分支合并到 Master

以下命令显示了使用 Git 将分支合并到 master 的一种方法:

$ git checkout master
$ git merge --no-ff contract-change-pr

在线工作

现在,您可以禁用 Spring Cloud Contract Stub Runner 的离线工作,并指示 包含存根的存储库所在的位置。此时,服务器的存根 side 会自动从 Nexus/Artifactory 下载。您可以设置stubsModeREMOTE.以下代码显示了 通过更改 properties 来实现相同的目的:

就是这样。您已完成本教程。