微服务契约测试策略

集成契约测试是在外部服务的边界上进行的测试,以验证它是否满足消费服务所期望的契约。

每当一些消费者连接到组件的接口以利用其行为时,它们之间就会形成契约。该合同包括对输入和输出数据结构、副作用、性能和并发特性的预期。

组件的每个消费者根据其需求形成不同的契约。如果组件随着时间的推移会发生变化,那么每个消费者的契约必须持续得到满足,这一点很重要。

集成契约测试提供了一种机制来显式验证组件是否满足契约。

当涉及的组件是微服务时,接口是每个服务公开的公共API。每个消费服务的维护者编写独立的测试套件,只验证正在使用的生产服务的那些方面。

这些测试不是组件测试。它们不会深入测试服务的行为,而是测试服务调用的输入和输出是否包含所需的属性,以及响应延迟和吞吐量是否在可接受的范围内。

理想情况下,每个消费团队编写的契约测试套件在生产服务的构建管道中被打包并可运行。通过这种方式,生产服务的维护者知道他们的更改对消费者的影响。

所有消费者契约测试的总和定义了整个服务契约

尽管契约测试为外部服务的消费者提供了信心,但它们对这些服务的维护者更有价值。通过从服务的所有消费者那里接收契约测试套件,在消费者不会受到影响的情况下,可以安全地对该服务进行更改。

考虑一个服务,它公开一个具有三个字段的资源:标识符、名称和年龄。该服务已被三个不同的使用者采用,它们分别与资源的不同部分相耦合。

消费者A只与标识符和名称字段配对。因此,对应的契约测试套件断言资源响应包含这些字段。它没有对年龄字段做任何断言。

消费者B连接到标识符和年龄字段,因此契约测试断言它们存在,但对名称字段不做断言。

消费者C需要所有三个字段,并有一个契约测试套件断言它们都存在。

如果新的使用者采用API,但同时需要名和姓,则维护人员可以选择弃用name字段,并引入另一个包含具有name组件的复合对象的字段。

为了了解需要什么来删除旧的名称字段,维护人员可以从响应中删除它,并查看哪些契约测试失败。在这种情况下,他们会看到消费者A和C需要被通知弃用。消费者A和C迁移到新字段后,可以删除已弃用的字段。

为了有效地实现这一点,生产者和消费者在序列化和反序列化消息时都应该遵循Postel定律,忽略对他们不重要的任何字段。

这种方法是并行更改的一个例子,其中API可以在一段时间内进行更改,而不会破坏任何消费者的契约。

在定义新服务时,契约测试套件也很有价值。消费者可以通过构建一套测试来驱动API设计,这些测试表达了他们对服务的需求。

这些消费者驱动的契约形成了与负责构建服务的团队的讨论点,以及提供API就绪指示的自动化测试。
有许多工具可以帮助编写契约测试,如Pact、Pacto和Janus。

转载翻译自: Testing Strategies in a Microservice Architecture