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:
-
To ensure that HTTP and messaging stubs (used when developing the client) do exactly what the actual server-side implementation does.
-
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.