单元测试基础应用

单元测试应用

开发人员写的常常是“单元测试”,但其实可以细分成 单元测试集成测试 两个。

单元测试

单元测试:是指对软件中的最小可测试单元进行检查和验证。

单元测试是编写测试代码,用来检测特定的、明确的、细颗粒的功能。单元测试并不一定保证程序功能是正确的,更不保证整体业务是准确的。

单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复改进重构之后的正确性。

单元测试不验证应用程序代码是否和外部依赖正常工作。它聚焦与单个组件并且 Mock 所有和它交互的依赖。例如,方法中调用发短信的服务,以及和数据库的交互,我们只需要 Mock 假执行即可,毕竟测试的焦点在当前方法上。

单元测试的特点:

  • 不依赖任何模块。
  • 基于代码的测试,不需要在 ApplicationContext 中运行。
  • 方法执行快,500ms以内(也和不启动 Spring 有关)。
  • 同一单元测试可重复执行N次,并每次运行结果相同。

单元测试任务包括

  1. 接口功能测试:用来保证接口功能的正确性。
  2. 局部数据结构测试(不常用):用来保证接口中的数据结构是正确的
    1. 比如变量有无初始值
    2. 变量是否溢出
  3. 边界条件测试
    1. 变量没有赋值(即为NULL)
    2. 变量是数值(或字符)
      1. 主要边界:最小值,最大值,无穷大(对于DOUBLE等)
      2. 溢出边界(期望异常或拒绝服务):最小值-1,最大值+1
      3. 临近边界:最小值+1,最大值-1
    3. 变量是字符串
      1. 引用“字符变量”的边界
      2. 空字符串
      3. 对字符串长度应用“数值变量”的边界
    4. 变量是集合
      1. 空集合
      2. 对集合的大小应用“数值变量”的边界
      3. 调整次序:升序、降序
    5. 变量有规律
      1. 比如对于Math.sqrt,给出n2-1,和n2+1的边界
  4. 所有独立执行通路测试:保证每一条代码,每个分支都经过测试
    1. 代码覆盖率
      1. 语句覆盖:保证每一个语句都执行到了
      2. 判定覆盖(分支覆盖):保证每一个分支都执行到
      3. 条件覆盖:保证每一个条件都覆盖到true和false(即if、while中的条件语句)
      4. 路径覆盖:保证每一个路径都覆盖到
    2. 相关软件
      1. Cobertura:语句覆盖
      2. Emma: Eclipse插件Eclemma
  5. 各条错误处理通路测试:保证每一个异常都经过测试

集成测试

集成测试:在单元测试的基础上,将所有模块按照设计要求组装成为子系统或系统,进行集成测试。

集成测试主要用于发现用户端到端请求时不同模块交互产生的问题。集成测试范围可以是整个应用程序,也可以是一个单独的模块,取决于要测试什么。

在集成测试中,我们应该聚焦于从控制器层到持久层的完整请求。应用程序应该运行嵌入服务(例如:Tomcat)以创建应用程序上下文和所有 bean。这些 bean 有的可能会被 Mock 覆盖。

集成测试的特点:

  • 集成测试的目的是测试不同的模块一共工作能否达到预期。
  • 应用程序应该在 ApplicationContext 中运行。Spring boot 提供 @SpringBootTest 注解创建运行上下文。
  • 使用 @TestConfiguration 等配置测试环境。

JUnit4 & JUnit5

常见区别有:

  • JUnit4 所需 JDK5+ 版本即可,而 JUnit5 需 JDK8+ 版本,因此支持很多 Lambda 方法。
  • JUnit 4将所有内容捆绑到单个jar文件中。Junit 5由3个子项目组成,即JUnit Platform,JUnit Jupiter和JUnit Vintage。核心是JUnit Jupiter,它具有所有新的junit注释和TestEngine实现,以运行使用这些注释编写的测试。而JUnit Vintage包含对JUnit3、JUnit4的兼容,所以spring-boot-starter-test新版本pom中往往会自动exclusion它。
  • SpringBoot 2.2.0 开始引入 JUnit5 作为单元测试默认库,在 SpringBoot 2.2.0 之前,spring-boot-starter-test 包含了 JUnit4 的依赖,SpringBoot 2.2.0 之后替换成了 Junit Jupiter。

**JUnit4 **

JUnit4通过注解的方式来识别测试方法。目前支持的主要注解有:

  • @BeforeClass 全局只会执行一次,而且是第一个运行,是static方法
  • @Before 在测试方法运行之前运行
  • @Test 测试方法
  • @After 在测试方法运行之后允许
  • @AfterClass 全局只会执行一次,而且是最后一个运行,是static方法
  • @Ignore 忽略此方法

JUnit5 的注解

功能JUnit4JUnit5
声明一种测试方法@Test@Test
在当前类中的所有测试方法之前执行@BeforeClass@BeforeAll
在当前类中的所有测试方法之后执行@AfterClass@AfterAll
在每个测试方法之前执行@Before@BeforeEach
在每个测试方法之后执行@After@AfterEach
禁用测试方法/类@Ignore@Disabled
测试工厂进行动态测试NA@TestFactory
嵌套测试NA@Nested
标记和过滤@Category@Tag
注册自定义扩展NA@ExtendWith

RunWith 和 ExtendWith

在 JUnit4 版本,在测试类加 @SpringBootTest 注解时,同样要加上 @RunWith(SpringRunner.class)才生效,即:

@SpringBootTest
@RunWith(SpringRunner.class)
class ServiceTest {
...
}

但在 JUnit5 中,官网告知 @RunWith 的功能都被 @ExtendWith 替代,即原 @RunWith(SpringRunner.class) 被同功能的 @ExtendWith(SpringExtension.class) 替代。但 JUnit5 中 @SpringBootTest 注解中已经默认包含了 @ExtendWith(SpringExtension.class)。

因此,在 JUnit5 中只需要单独使用 @SpringBootTest 注解即可。其他需要自定义拓展的再用 @ExtendWith,不要再用 @RunWith 了。

具体JUnit5 的使用这篇不做详细介绍,该题应该另开一篇文章来描述

值得参考的文章:(5条消息) junit5 入门系列教程-01-junit5 简单入门例子_老马啸西风的博客-CSDN博客_junit5教程

使用Mockito

Mock 框架有很多,除了传统的 EasyMock、Mockito以外,还有PowerMock、JMock、JMockit等。个人一般选用用 Mockito和 PowerMock,因为 Mockito 在社区流行度较高,而且是 SpringBoot 默认集成的框架。用PowerMock来处理mock处理不了的static静态方法的mock。

Mockito 框架中最核心的两个概念就是 MockStub。测试时不是真正的操作外部资源,而是通过自定义的代码进行模拟操作。我们可以对任何的依赖进行模拟,从而使测试的行为不需要任何准备工作或者不具备任何副作用。

具体使用方法在官方文档中描述很全面很详细,这边不做赘述,链接如下

官方文档:GitHub - hehonghui/mockito-doc-zh: Mockito框架中文文档

代码覆盖率

在了解搜索相关内容时,发现代码覆盖率这块内容时不曾了解的,该方面内容待学习和补足。切入点: Jacoco,Eclmama

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值