Introducing Spring Cloud Contract
Spring Cloud Contract 将 TDD 转移到软件架构的级别。它允许您执行消费者驱动的和生产者驱动的契约测试。
Spring Cloud Contract moves TDD to the level of software architecture. It lets you perform consumer-driven and producer-driven contract testing.
History
在成为 Spring Cloud Contract 之前,该项目被称为 Accurest。 它由 ( Codearte) 的 Marcin Grzejszczak 和 Jakub Kubrynski 创建。
Before becoming Spring Cloud Contract, this project was called Accurest. It was created by Marcin Grzejszczak and Jakub Kubrynski from (Codearte).
0.1.0
版本于 2015 年 1 月 26 日发布,并于 2016 年 2 月 29 日随着 1.0.0
版本变得稳定。
The 0.1.0
release took place on 26 Jan 2015, and it became stable with 1.0.0
release on 29 Feb 2016.
Why Do You Need It?
假设我们拥有一个由多个微服务组成的系统,如下所示:
Assume that we have a system that consists of multiple microservices, as the following image shows:

Testing Issues
如果我们想要测试图像左上角的应用程序以确定它是否可以与其他服务通信,我们可以执行以下两件事之一:
If we want to test the application in the top left corner of the image in the preceding section to determine whether it can communicate with other services, we could do one of two things:
-
部署所有微服务并执行端到端测试。
-
Deploy all microservices and perform end-to-end tests.
-
在单元和集成测试中模拟其他微服务。
-
Mock other microservices in unit and integration tests.
两者都有各自的优点,但也有很多缺点。
Both have their advantages but also a lot of disadvantages.
部署所有微服务并执行端到端测试
Deploy all microservices and perform end-to-end tests
优点:
Advantages:
-
Simulates production.
-
测试服务之间的实际通信。
-
Tests real communication between services.
缺点:
Disadvantages:
-
要测试一个微服务,我们必须部署六个微服务、几个数据库和其他项目。
-
To test one microservice, we have to deploy six microservices, a couple of databases, and other items.
-
测试运行环境对一整套测试锁定(在此期间,其他任何人都不可以运行测试)。
-
The environment where the tests run is locked for a single suite of tests (nobody else would be able to run the tests in the meantime).
-
它们需要很长时间才能运行。
-
They take a long time to run.
-
反馈在流程中非常滞后。
-
The feedback comes very late in the process.
-
它们极难调试。
-
They are extremely hard to debug.
在单元和集成测试中模拟其他微服务
Mock other microservices in unit and integration tests
优点:
Advantages:
-
它们提供非常快的反馈。
-
They provide very fast feedback.
-
它们没有基础设施要求。
-
They have no infrastructure requirements.
缺点:
Disadvantages:
-
服务的实施者创建的存根可能与实际情况无关。
-
The implementor of the service creates stubs that might have nothing to do with reality.
-
您可以通过测试并失败生产,从而转入生产。
-
You can go to production with passing tests and failing production.
为了解决上述问题,生成了 Spring Cloud Contract。其主要思想是给你非常快速的反馈,无需设置整个微服务世界。如果你处理存根,那么你需要的唯一应用程序就是你的应用程序直接使用的应用程序。下图显示了存根与应用程序的关系:
To solve the aforementioned issues, Spring Cloud Contract was created. The main idea is to give you very fast feedback, without the need to set up the whole world of microservices. If you work on stubs, then the only applications you need are those that your application directly uses. The following image shows the relationship of stubs to an application:

Spring Cloud Contract 让你确信你使用的存根是由你调用的服务生成的。此外,如果你可以使用它们,这意味着它们已经针对生产者的一侧进行了测试。简而言之,你可以信任这些存根。
Spring Cloud Contract gives you the certainty that the stubs that you use were created by the service that you call. Also, if you can use them, it means that they were tested against the producer’s side. In short, you can trust those stubs.
Purposes
Spring Cloud Contract 的主要目的是:
The main purposes of Spring Cloud Contract are:
-
为了确保 HTTP 和消息传递存根(在开发客户端时使用)完全符合实际服务器端实现的功能。
-
To ensure that HTTP and messaging stubs (used when developing the client) do exactly what the actual server-side implementation does.
-
为了推广 ATDD(验收测试驱动开发)方法以及微服务架构样式。
-
To promote the ATDD (acceptance test-driven development) method, and the microservices architectural style.
-
为了提供一种发布合约更改的方式,在双方都可以立即看到这些更改。
-
To provide a way to publish changes in contracts that are immediately visible on both sides.
-
在服务器端生成要使用的样板测试代码。
-
To generate boilerplate test code to be used on the server side.
默认情况下,Spring Cloud Contract 与 Wiremock 集成在一起,将其作为 HTTP 服务器存根。
By default, Spring Cloud Contract integrates with Wiremock as the HTTP server stub.
Spring Cloud Contract 的目标不是在契约中开始编写业务功能。假设我们有一个欺诈检查的业务用例。如果一个用户因 100 个不同的原因而可能成为欺诈者,我们假设你会创建两个契约,一个用于正面案例,一个用于负面案例。契约测试用于测试应用程序之间的契约,而不是模拟完整行为。
Spring Cloud Contract’s purpose is NOT to start writing business features in the contracts. Assume that we have a business use case of fraud check. If a user can be a fraud for 100 different reasons, we would assume that you would create two contracts, one for the positive case and one for the negative case. Contract tests are used to test contracts between applications, not to simulate full behavior.
What Is a Contract?
作为服务消费者,我们需要定义我们究竟想要实现什么。我们需要表述我们的期望。这就是我们编写合同的原因。换句话说,合同是对 API 或消息通信应如何表现的约定。请考虑以下示例:
As consumers of services, we need to define what exactly we want to achieve. We need to formulate our expectations. That is why we write contracts. In other words, a contract is an agreement on how the API or message communication should look. Consider the following example:
假设你想要发送一个请求,其中包含客户公司的 ID 和它想要从我们这里借贷的金额。你还想要使用 PUT
方法将它发送到 /fraudcheck
URL。以下清单显示了用于检查客户端是否应该在 Groovy 和 YAML 中标记为欺诈的合同:
Assume that you want to send a request that contains the ID of a client company and the
amount it wants to borrow from us. You also want to send it to the /fraudcheck
URL by using
the PUT
method. The following listing shows a contract to check whether a client should
be marked as a fraud in both Groovy and YAML:
-
groovy
Unresolved directive in introducing-spring-cloud-contract.adoc - include::{samples_path}/standalone/dsl/http-server/src/test/resources/contracts/fraud/shouldMarkClientAsFraud.groovy[]
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。你不应该下载或与来自不受信源的契约进行交互。
It is expected that contracts are coming from a trusted source. You should never download nor interact with contracts coming from untrusted locations.