对于我们发送数据包不是请求的消息队列,是否应该避免契约测试?

问题描述

似乎契约测试不会为消息队列带来任何好处。有什么好处吗?

在提供者端,我们实例化一个通常会进入 kafka 的对象。

所以提供者的本质是这样的:

  • 一个数据对象实例(在内存中)
  • 序列化(由 kafka 库)
  • 序列化并用于 Pact 合同验证。

在消费者方面,我们有相反的做法,即我们在内存中重新创建该对象并触发使用它的代码

换句话说,消费者的本质是:

  • 从 kafka 队列(在本例中为 Pact 的模拟队列)读取数据包
  • 将对象反序列化为对象实例
  • 尝试触发使用该对象的代码

就我而言,在消费者方面,无法触发使用对象的代码。这是因为它需要启动服务器本身的一个实例,这引入了很多复杂性。

当我们发送数据包(不是请求)时,是否应该避免对消息队列进行契约测试?

重要的是要记住契约测试 =|= 功能测试。 所以我们不会用不同的消息重新测试,因为那将是功能测试。

解决方法

合约测试的价值

合同测试询问“这些服务是否能够相互通信”。这个问题对于消息队列绝对有价值。

部署新版本的消费者安全吗?这取决于生产者是否能够阅读和理解提供者发送的消息。合同测试可提高您对消费者和提供者能够相互交流的信心。

您可能会争辩说,对于消息队列,合同测试很重要,因为(取决于设计和消息在队列中存在的时间长短/是否重播),您可能正在使用由几个不同版本的制作人制作。

即使使用者和提供者位于同一个部署单元(例如,单个微服务),您也可能会在部署发生后立即使用来自先前版本的提供者的消息。

理论

从理论上讲,合同测试消息队列就像合同测试 HTTP 请求/响应对,其中请求是隐式的(您可以认为“请求”是对队列的订阅)。

练习

在测试/验证 HTTP Pact 合同时,Pact 提供传输(模拟 HTTP 客户端/服务器)和内容(内容形状和约束)。

目前,当用 Message Pact 做同样的测试时,Pact 只提供内容/约束。没有模拟消费者/提供者——数​​据传输没有经过 Pact 框架的测试。这意味着消息协议测试的覆盖范围比相应的 HTTP 协议略少 - 它不是测试您的队列库是否已正确设置和调用(除非您自己进行测试)。

Pact Spec V4 Plugin proposal 的存在是为了在未来更容易解决这个差距,以便消息契约测试也能够更容易地覆盖队列库。但是,这不是今天可以使用的东西。

您的具体情况

它需要启动服务器本身的一个实例,这会带来很多复杂性。

感觉这可能是一个软件设计问题,稍微重构一下就可以解决。您应该能够在不启动整个服务器的情况下运行消息契约消费者测试。这将特定于您的用例和设计,但请在 https://slack.pact.io/#general 加入我们,我们可能会为您提供帮助。

合同测试不是功能测试

重要的是要记住契约测试 =|= 功能测试。所以我们不会用不同的消息重新测试,因为那将是功能测试。

是的,这是一个很好的观察。一般来说,你想测试你的消费者是否能够理解提供者可以发送的每一种类型的消息,而在消息队列的情况下,这通常只是一种类型(尽管有时仍然是几种)。

这有点偏离您的问题的主题,但这里有一个小小的警告,尽管 Pact 测试不是功能测试,但如果它具有一些功能覆盖就可以了。所有测试都是为了降低风险——您越接近测试将要运行的实际代码,风险就越低。出于这个原因,我通常在服务中尽可能深入地放置任何模拟。当然,我会用自己的单元测试来覆盖服务的行为,但我认为如果契约测试(不直接覆盖行为)碰巧在合同验证过程中仍然行使一些行为,那就好了.如果您需要,很乐意详细说明。