使用 Pact 和 Quarkus 驯服微服务测试
在微服务架构中,确保每个微服务都能正常工作(相对而言)是很容易的。微服务通常很小,易于测试。但如何确保微服务协同工作呢?如何知道整个系统是否正常工作?
一个答案是契约测试。契约测试比测试单个服务能提供更多信心,而成本远低于端到端测试。
Mock 有什么问题?
当测试“真实”的系统其余部分过于沉重时,团队通常会使用 mock 或 stub。(Mock 和 stub 有细微差别,但为简单起见,我将使用“mock”来描述两者。)Mock 有很多优点;它们轻量级,并且能够对具有外部依赖的代码进行单元测试。但是,mock 也有一个很大的缺点;不能保证 mock 的行为与真实事物相同。服务的使用者会在 mock 中烘焙他们自己对服务行为的假设。如果服务发生更改,消耗代码需要弄清楚发生了什么变化并更新 mock。
有时,这些假设第一次得到测试是在生产环境中。
契约测试
如何将消费者使用的 mock 与提供者进行的功能验证联系起来?这就是契约测试的作用。契约测试框架支持两件事:
-
生成的 mock,由消费者使用以验证消费者代码是否正常运行。mock 是根据契约和示例生成的。
-
生成的函数式测试,用于验证提供者的行为是否符合预期。这些测试是根据与消费者 mock 相同的契约和示例生成的。
通过测试驱动开发 (TDD),您从测试(所需行为的描述)开始,然后倒推实现。您也可以使用契约测试做同样的事情;您从描述服务需要做什么的契约开始,然后倒推实现。这被称为“契约优先”,它可以是一种非常有效的开发技术。我在 Red Hat App Dev Consulting 的同事们撰写了一些关于他们如何使用契约优先开发的优秀文章。
契约测试选项
目前有几种不同的契约测试框架,包括 Pact、Microcks、Spring Cloud Contract。一些团队还构建了自己的基于 OpenAPI 的工具链,例如用于函数式测试的 Schemathesis 和用于 mock 的 Prism。Pact 可能是最流行的契约测试解决方案,因此 Quarkiverse 的契约测试支持就从这里开始。
-
Pact 是多语言的,几乎支持所有流行语言的绑定。
-
它是一个集成解决方案,为消费者提供 mock,并为提供者提供函数式测试。
-
它是独立的,可以在不启动任何额外服务的情况下运行,尽管也提供了一个带有附加功能的 Pact Broker。
-
尽管 Pact 最初是作为仅 REST 的解决方案开始的,但它现在是可插拔的,这使其能够支持各种协议和传输。
Pact 团队对基于模式的测试(如基于 OpenAPI 规范的验证)和契约测试的优缺点进行了良好概述。
Pact 和 Quarkus 的新变化
在 Quarkus 中使用 Pact 并不是什么新鲜事;Quarkus 贡献者在 Quarkus 2.0 中对 Quarkus 核心进行了几次类加载调整以支持 Pact 测试,但这种支持是有限的。特别是,Pact 测试无法在持续测试模式下运行。
Quarkus 3.0 将 Pact 支持从 Quarkus 核心移至其自身的 Quarkiverse 扩展,在那里可以更深入。Quarkus 核心还包括 Kotlin 扩展中的类加载更改以及持续测试本身的一些类加载修复。这意味着,通过 Pact Quarkiverse provider 和 consumer 扩展,Pact 测试可以与 `quarkus test` 和 `quarkus dev` 正常工作。
要安装消费者扩展,请运行
quarkus ext add io.quarkiverse.pact:quarkus-pact-consumer
可以使用以下命令安装提供者扩展
quarkus ext add io.quarkiverse.pact:quarkus-pact-provider
要深入了解契约测试,请查看Quarkus Insights #117。