Home
img of docs

分享在项目中进行单元测试的意义,执行和编写原则,为什么要使用 mock

chou403

/ UnitTest

/ c:

/ u:

/ 6 min read


什么是单元测试

单元测试又称为模块测试,是针对程序模块来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序,函数,过程等,对于面向对象编程,最小单元就是方法,包括基类,抽象类,或者派生中的方法。它是软件开发中的一种测试方法,通常由软件开发人员编写,用于测试他们正在开发的代码是否按照预期方法运行,主要目标是验证软件中最小的,可测试,独立的业务单元的正确性。

单元测试的意义

单元测试是产品质量控制左移的重要一环,它强调在软件开发生命周期的早期阶段就开始关注和提升质量,而不是等到产品开发完成后才进行质量检查。这种方法的目的是尽早的发现和解决问题,从而减少后期修复的成本和时间,提高最终产品的质量并降低项目风险。

单元测试的原则 AIR+FIRST(执行原则)

  1. A-Automatic(自动化) 单元测试应该是全自动执行的,无需人工干预
  2. F-Fast(快速的) 有单元测试应该是可以快速运行的,在各种测试方法中,单元测试的运行速度是最快的,大型项目的单元测试通常应该在几分钟内运行完毕,平均每个单侧用例执行不超过 60 毫秒。
  3. I-Independent(独立的) 单元测试应该是可以独立运行的,单元测试用例互相之间无依赖,且对外部资源也无任何依赖。比如,单元测试不可依赖不属于自己的数据,或者一些特定机器才有的环境变量,这些数据/变量需要 mock 进行隔离。
  4. R-Repeatable(可重复的) 单元测试应该可以稳定重复的运行,并且每次运行的结果都是稳定可靠的。
  5. S-SelfValidating(自我验证) 单元测试应该是用例自动进行验证的,不能依赖人工验证。
  6. T-Timely(及时的) 单元测试必须及时进行编写,更新和维护,以保证用例可以随着业务代码的变化动态的保障质量。

单元测试的原则 BCDE(测试用例编写原则)

编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。

  1. B-Border: 边界值测试,包括循环边界,特殊取值,特殊时间点,数据顺序等。
  2. C-Correct: 正确的输入,并得到预期的结果。
  3. D-Design: 与设计文档相结合,来编写单元测试。
  4. E-Error: 强制错误信息输入(如: 非法数据,异常流程,非业务允许输入等),并得到预期的结果。测试的目标是验证代码的健壮性是否达到预期设计,所以不能只测试乐观路径,而是对乐观路径和悲观路径都进行测试。

覆盖率相关: 建议 80%,80%的百分比是单元测试成功的必要条件,但不是充分条件。

单元测试 mock 的重要性

什么是 mock

模拟对象的行为,达到屏蔽掉外部依赖的效果。 模拟一个方法的输入获得方法的输出。

单元测试为什么要 mock

  • F-Fast(快速的): 单元测试可以快速运行
  • I-Independent(独立的): 无依赖可以独立运行
  • R-Repeatable(可重复的): 稳定重复运行,每次运行结果稳定可靠

单元测试常用注解

Junit

  • @ExtendWith: 声明性的注册拓展
  • @Test: 标识方法为一个测试用例
  • @BeforeAll: 所有方法之前,执行一次
  • @AfterAll: 所有方法之后,执行一次
  • @AfterEach: 每个方法之执行
  • @ParameterizedTest: 参数化测试方法
  • @TimeOut: 设置超时时间
  • @Order: 设置测试方法的执行顺序
  • @RepeatedTest: 重复执行的次数
  • @Disabled: 标识禁用的测试类和方法
  • @DisplayName: 类或方法自定义显示名称

Mockito

  • @Mock: 创建被 mock 的代理对象
  • @Spy: 创建被 spy 的代理对象,可保留原对象的行为
  • @InjectMocks: 创建真实对象,常用于被测试类,可注入 mock 对象
  • @Captor: 用于捕获方法调用的参数,方便进一步的断言和校验
  • @MockitoSettings: 用于设置 Mockito 框架的全局设置

SpringBoot

  • @MockBean: 创建被 Spring 管理的 mock bean,常用于集成测试中
  • @SpyBean: 创建被 Spring 管理的 spy bean,常用于集成测试中