TomasFernandez译者|朱刚策划|Xinyuan在测试方面,微服务需要不同的方法。微服务应用程序是一组分布式程序,它们通过网络进行通信并与第三方服务和数据库接口进行交互。微服务,就其网络性质而言,比传统的单体架构有更多的故障点。因此,我们需要一种不同的、更广泛的测试方法。那么,我们如何测试微服务应用呢?测试金字塔仍然有效吗?我们如何测试何时涉及第3方服务并且可能出现网络中断?我们将在本文中尝试回答所有这些问题。测试微服务的挑战微服务架构是一个深刻的范式转变,我们不得不重新思考传统的测试技术。微服务在许多方面不同于经典的单体架构:分布式:微服务部署在多个服务器上,可能会增加跨地理位置的延迟,并使应用程序面临连接网络中断的风险。依赖于网络的测试可能会因代码没有错误而失败,从而破坏CI/CD管道并阻碍开发。自治:开发团队可以随时自由部署他们的微服务,只要不破坏API兼容性即可。增加测试区域:由于每个微服务都有多个API节点,因此可以覆盖更多的可测试表面。多语言:开发团队可以为他们的微服务选择最好的语言。在大型系统中,我们不太可能找到适合所有组件的测试框架。生产是一个移动的目标:由于微服务可由自主团队独立部署和构建,因此需要额外的检查和边界以确保它们在部署时仍能正常协同工作。所有这些特征迫使我们考虑新的测试策略。微服务测试金字塔测试金字塔是一种用于自动化软件测试的规划工具。在传统形式中,Pyramid使用三种类型的测试:单元测试集成测试端到端测试微服务Pyramid增加了两种新类型:组件测试和合同测试。这是微服务测试金字塔的一个版本。在其他情况下,顺序可能会有所不同。有些可能在集成层中包含合同测试。金字塔与其说是刻在石头上的东西,不如说是一种指导方针。让我们仔细看看每个金字塔层是如何工作的。微服务的单元测试单元测试是最细化和最庞大的测试形式之一。一个单元由可以单独测试的类、方法或函数组成。单元测试是测试驱动开发或行为驱动开发等开发实践的组成部分。与单体架构相比,微服务中的单元需要网络调用来实现其功能的可能性要高得多。当发生这种情况时,我们可以让代码访问外部服务(接受一些延迟和非确定性),或者用mock替换调用,这为我们提供了两种处理微服务依赖的方法:独立单元测试:应该使用这种测试当我们需要测试结果始终是确定性的。我们使用模拟或存根将被测代码与外部依赖项隔离开来。社会化单元测试:允许社会化测试调用其他服务。在这种模式下,我们将测试的复杂性推到测试或暂存环境中。社会化测试是不确定的,但当它们通过时,我们可以对它们的结果更有信心。我们可以使用Mock单独运行单元测试。或者我们可以让被测代码调用其他微服务,在这种情况下我们谈论的是社交测试。如您所见,平衡信心和稳定性将是贯穿本文的主题。模拟使测试更快、不确定性更低,但模拟得越多,结果就越不可信。社会化测试尽管有缺点,但更现实。因此,您可能需要在这两种类型之间取得良好的平衡。合同测试只要两个服务通过接口耦合,合同就会形成。合约指定所有可能的输入和输出及其数据结构和副作用。服务的消费者和生产者必须遵守合同规定的规则才能进行沟通。合同测试确保微服务遵守他们的合同。他们没有彻底测试服务的行为;他们只确保输入和输出具有预期的特性,并且服务在可接受的时间和性能限制内执行。根据服务之间的关系,合同测试可以由生产者和/或消费者运行。消费者端合同测试,由下游团队编写和执行。在测试期间,微服务会连接到创建者服务的伪造或模拟版本,以检查它是否可以使用其API。生产者端合同测试在上游服务中运行。这种类型的测试模拟客户端可以发出的各种API请求,验证生产者是否与合同相匹配。生产者端测试让开发人员知道他们何时破坏了消费者兼容性。合同测试可以在上游或下游运行。生产者测试检查服务没有实施会破坏服务的更改。消费者测试针对上游生产者的模拟版本(不是真正的生产者服务)运行消费者端组件,以验证消费者是否可以发出请求并使用来自生产者的预期响应。我们可以使用WireMock等工具来重现HTTP请求。如果合约测试通过,则生产者和消费者是兼容的并且应该能够通信。合同测试应始终在持续集成中运行,以在部署前检查兼容性。您可以在《Pact 5-minute getting started guide》进行在线合同测试。Pact是一种基于HTTP的测试工具,用于编写和运行基于消费者和生产者的契约测试。微服务集成测试微服务集成测试的工作方式与其他架构略有不同。它的目标是通过使微服务交互来识别接口缺陷。与总是模拟侧面的合同测试不同,集成测试使用真实的服务。集成测试对评估服务的行为和业务逻辑不感兴趣。相反,我们希望确保微服务可以相互通信,并与它们自己的数据库正确通信。我们正在寻找诸如缺少HTTP请求标头或不匹配的请求/响应对之类的问题。因此,集成测试通常在接口级别实现。使用集成测试来检查微服务是否可以与其他服务、数据库和第三方端点进行通信。微服务的组件测试组件是一个微服务或一组微服务,它们在更大的系统中发挥作用。组件测试是一种验收测试,我们通过用模拟资源或模拟替换服务来检查组件的行为。组件测试比集成测试更彻底,因为它们经历了“快乐”和“不快乐”的路径。示例包括组件如何响应模拟网络中断或格式错误的请求。我们想知道组件是否满足其消费者的需求,就像我们在验收或端到端测试中所做的那样。组件测试对一组微服务执行端到端测试。组件范围之外的服务被模拟。执行组件测试有两种方法:进程内和进程外。进程内组件测试在这个组件测试子类中,测试运行器与微服务存在于同一个线程或进程中。我们以“离线测试模式”启动微服务,其中所有依赖项都被模拟,允许我们在没有网络的情况下运行测试。在与微服务相同的进程中运行的组件测试。该测试在适配器中注入模拟服务以模拟与其他组件的交互。进程内测试仅在组件是单个微服务时才有效。乍一看,组件测试与端到端或验收测试非常相似。唯一的区别是组件测试选择系统的一个部分(组件)并将其与其他部分隔离。该组件经过全面测试,以验证它是否执行其用户或消费者所需的功能。组件测试和端到端测试可能看起来很相似。但不同之处在于端到端在类似生产的环境中测试整个系统(所有微服务),而组件在整个系统的孤立部分进行测试。两种类型的测试都从用户(或消费者)的角度检查系统的行为,遵循用户将执行的操作。我们可以用任何语言或框架编写组件测试,但最流行的可能是Cucumber和Capybara。进程外组件测试进程外测试适用于任何规模的组件,包括由许多微服务组成的组件。在这种类型的测试中,组件部署在所有外部依赖项都被模拟或存根的测试环境中。在这种类型的组件测试中,复杂性被推入了测试环境,它应该复制系统的其余部分。要细化合同测试的概念,您可以探索《Java Spring上合约测试的示例代码?》。此外,如果您是Java开发人员,本文还提供了用于在各个级别测试Java微服务的代码示例。微服务中的端到端测试到目前为止,我们已经对系统进行了零碎的测试。单元测试用于测试微服务的各个部分,契约测试涵盖API兼容性,集成测试检查网络调用,组件测试验证子系统的行为。只有在自动化测试金字塔的顶端,我们才能测试整个系统。端到端(E2E)测试可确保系统满足用户需求并实现业务目标。E2E套件应该覆盖应用程序中的所有微服务,具有与用户相同的界面,通常结合使用UI和API测试。应用程序应尽可能接近生产运行。理想情况下,测试环境将包括应用程序通常需要的所有第三方服务,但有时可以模拟这些服务以降低成本或防止滥用。端到端是模拟用户交互的自动化测试。只能模拟外部第三方服务。正如测试金字塔所描述的,端到端测试数量最少,因为它们通常最难运行和维护。只要我们关注用户的行为和他们的需求,我们就可以通过一些端到端的测试来提取大量的资源价值。结论不同的模式需要改变测试策略。在微服务架构中进行测试比以往任何时候都更加重要,但我们需要使我们的技术适应新的开发模型。系统不再由一个团队管理。相反,每个微服务所有者都必须尽自己的一份力量来确保应用程序作为一个整体运行。一些组织可能认为单元、合同和组件测试就足够了。其他不满足于没有端到端和集成测试的人可能会选择建立一个QA团队来促进跨团队测试覆盖。译者介绍朱刚,社区编辑,2021IT影响力专家博主,阿里云专家博主,2019CSDN博客之星Top20,2020腾讯云+社区优秀作者,11年一线开发经验,曾参与猎头服务网站架构设计、企业智能客服及大型电子政务系统开发,主导某大型央企内部防泄密及电子文档安全监控系统建设,目前在北京途家健康从事医疗软件研发。原标题:TestingStrategiesforMicroservices,作者:TomasFernandez链接:https://dzone.com/articles/testing-strategies-for-microservices
