微服务架构设计模式笔记--第九章 微服务架构中的测试策略(上)
传统的测试方法通常都在开发完成后执行,开发人员将他们的代码扔给隔壁的QA团队,QA团队验证软件是否按预期工作。更糟糕的是,他们的大多数测试都是手动执行的。这种测试方法现在不管用了,原因有两个:
- 手动测试效率极低:你永远不应该让人类去做一台机器可以做得更好的事情。与机器相比,手动测试执行的速度很慢,不能全天候工作。如果依赖手动测试,你将无法快速且安全地交付高质量的软件。编写自动化测试至关重要。
- 在交付流程中才进行测试为时已晚:在编写应用程序之后,确实应该通过测试来找出软件潜在的问题,但经验表明这些测试不够充分。一种更好的方式是让开发人员编写自动化测试,以此作为开发的一部分。自动化测试可以提高开发人员的工作效率,例如,当他们在修改代码时,自动化测试用例可以给他们提供及时的反馈。
1. 微服务架构中的测试策略概述
1.1 什么是测试
如图所示,测试的目的是验证被测系统的行为。在这个定义中,系统只是一个泛称,它指的是被测试的软件元素。它可以小到一个类,大到整个应用,或者介于两者之间,例如一组相关的类、模块或单个服务。一组相关的测试用例集构成一个测试套件。
编写自动化测试的4个阶段:
- 设置环境:将被测系统以及其他相关元素组成的测试环境初始化为所需的状态。例如,创建测试中的类,并将其初始化为呈现特定行为所需的状态。
- 执行测试:调用被测系统,例如,在被测试的类上调用一个方法。
- 验证结果:对调用的返回结果和被测系统的状态进行判断。例如,验证方法的返回值
和被测试类的新状态与预期一致。 - 清理环境:必要时清理测试环境。许多测试省略了这个阶段,但是某些类型的测试,
比如涉及数据库的测试可能需要在这个阶段将数据库的状态回滚到设置环境阶段前的初始状态。
使用模拟和桩进行测试:Mockito是一种流行的Java模拟对象框架。
测试的不同类型:
- 单元测试:测试服务的一小部分,例如类。
- 集成测试:验证服务是否可以与基础设施服务(如数据库)或其他应用程序服务进行交互。
- 组件测试:单个服务的验收测试。
- 端到端测试:整个应用程序的验收测试。
使用测试金字塔指导测试工作
1.2 微服务架构中的测试挑战
消费者驱动的契约测试:
消费者驱动的契约测试通常使用样例测试。消费者和提供者之间的交互由一组样例定义,称为契约。每个契约都包含在一次交互期间交换的样例消息。
例如,RESTAPI的契约包含示例HTTP请求和响应。从表面上看,使用例如Open API或JSON编写的模式来定义这些交互似乎很有用。但事实证明,在编写测试时,模式并不是那么有用。测试可以使用模式来验证响应,但仍需要使用样例请求调用提供者程序。
使用Spring Cloud的契约测试服务:Spring Cloud Contract
1.3 部署流水线
部署流水线通常使用持续集成(Continuous Integration)服务器(如Jenkins)实现。
图中显示的示例部署流水线包含以下阶段:
- 提交前测试阶段:执行单元测试。这是由开发人员在提交代码更改之前执行的。
- 提交测试阶段:编译服务,执行单元测试,并执行静态代码分析。
- 集成测试阶段:执行集成测试。
- 组件测试阶段:执行服务的组件测试。
- 部署阶段:将服务部署到生产环境中。
2. 为服务编写单元测试
如图所示,单元测试是测试金字塔的最低级别。它们是面向技术的测试,目标是协助开发。单元测试验证单元(服务的很小的一部分)是否正常工作。单元通常是一个类,此单元测试的目标是验证这个类的行为是否符合预期。
有两种类型的单元测试:
- 独立型单元测试:使用针对类的依赖性的模拟对象隔离测试类。
- 协作型单元测试:测试一个类及其依赖项。
类的职责决定是使用独立型单元测试还是协作型单元测试。
- 为实体编写单元测试
- 为值对象编写单元测试
- 为Saga编写单元测试
- 为领域服务编写单元测试
- 为控制器编写单元测试Spring Mock Mvc
- 为事件和消息处理程序编写单元测试
自动化测试是快速、安全地交付软件的重要基石。更重要的是,由于微服务架构固有的复杂性,要从微服务架构中充分受益,必须实现自动化测试。