Introducing Spring Cloud Contract

Spring Cloud Contract 将 TDD 转移到软件架构的级别。它允许您执行消费者驱动的和生产者驱动的契约测试。

History

在成为 Spring Cloud Contract 之前,该项目被称为 Accurest。 它由 ( Codearte) 的 Marcin GrzejszczakJakub Kubrynski 创建。

0.1.0 版本于 2015 年 1 月 26 日发布,并于 2016 年 2 月 29 日随着 1.0.0 版本变得稳定。

Why Do You Need It?

假设我们拥有一个由多个微服务组成的系统,如下所示:

Deps

Testing Issues

如果我们想要测试图像左上角的应用程序以确定它是否可以与其他服务通信,我们可以执行以下两件事之一:

  • 部署所有微服务并执行端到端测试。

  • 在单元和集成测试中模拟其他微服务。

两者都有各自的优点,但也有很多缺点。

部署所有微服务并执行端到端测试

优点:

  • Simulates production.

  • 测试服务之间的实际通信。

缺点:

  • 要测试一个微服务,我们必须部署六个微服务、几个数据库和其他项目。

  • 测试运行环境对一整套测试锁定(在此期间,其他任何人都不可以运行测试)。

  • 它们需要很长时间才能运行。

  • 反馈在流程中非常滞后。

  • 它们极难调试。

在单元和集成测试中模拟其他微服务

优点:

  • 它们提供非常快的反馈。

  • 它们没有基础设施要求。

缺点:

  • 服务的实施者创建的存根可能与实际情况无关。

  • 您可以通过测试并失败生产,从而转入生产。

为了解决上述问题,生成了 Spring Cloud Contract。其主要思想是给你非常快速的反馈,无需设置整个微服务世界。如果你处理存根,那么你需要的唯一应用程序就是你的应用程序直接使用的应用程序。下图显示了存根与应用程序的关系:

Stubs2

Spring Cloud Contract 让你确信你使用的存根是由你调用的服务生成的。此外,如果你可以使用它们,这意味着它们已经针对生产者的一侧进行了测试。简而言之,你可以信任这些存根。

Purposes

Spring Cloud Contract 的主要目的是:

  • 为了确保 HTTP 和消息传递存根(在开发客户端时使用)完全符合实际服务器端实现的功能。

  • 为了推广 ATDD(验收测试驱动开发)方法以及微服务架构样式。

  • 为了提供一种发布合约更改的方式,在双方都可以立即看到这些更改。

  • 在服务器端生成要使用的样板测试代码。

默认情况下,Spring Cloud Contract 与 Wiremock 集成在一起,将其作为 HTTP 服务器存根。

Spring Cloud Contract 的目标不是在契约中开始编写业务功能。假设我们有一个欺诈检查的业务用例。如果一个用户因 100 个不同的原因而可能成为欺诈者,我们假设你会创建两个契约,一个用于正面案例,一个用于负面案例。契约测试用于测试应用程序之间的契约,而不是模拟完整行为。

What Is a Contract?

作为服务消费者,我们需要定义我们究竟想要实现什么。我们需要表述我们的期望。这就是我们编写合同的原因。换句话说,合同是对 API 或消息通信应如何表现的约定。请考虑以下示例:

假设你想要发送一个请求,其中包含客户公司的 ID 和它想要从我们这里借贷的金额。你还想要使用 PUT 方法将它发送到 /fraudcheck URL。以下清单显示了用于检查客户端是否应该在 Groovy 和 YAML 中标记为欺诈的合同:

  • groovy

Unresolved directive in introducing-spring-cloud-contract.adoc - include::{samples_path}/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[]
yaml
Unresolved directive in introducing-spring-cloud-contract.adoc - include::{samples_path}/standalone/dsl/http-server/src/test/resources/contracts/yml/fraud/shouldMarkClientAsFraud.yml[]

据预期,契约来自一个 trusted source。你不应该下载或与来自不受信源的契约进行交互。