java 单元测试学习

单测的标准:

语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都要达到100%。 --- 《阿里巴巴Java开发手册》

单测覆盖度分级参考

Level1:正常流程可用,即一个函数在输入正确的参数时,会有正确的输出

Level2:异常流程可抛出逻辑异常,即输入参数有误时,不能抛出系统异常,而是用自己定义的逻辑异常通知上层调用代码其错误之处

Level3:极端情况和边界数据可用,对输入参数的边界情况也要单独测试,确保输出是正确有效的

Level4:所有分支、循环的逻辑走通,不能有任何流程是测试不到的

Level5:输出数据的所有字段验证,对有复杂数据结构的输出,确保每个字段都是正确的

60%左右的单测覆盖率可以非常轻松达到,但达到95%以上的覆盖率,需要覆盖各种代码分支和异常情况等,甚至是配置和bean的初始化方法,所投入的时间非常巨大,但边际效应递减。我想测试toString, getter/setter这样的方法也没有意义。多少合适,我认为没有一个固定的标准。高代码覆盖率百分比不表示成功,也不意味着高代码质量。该舍弃测试的部分就大胆的ignore掉。

1、隐藏的测试边界值

2、不要在springboot测试中使用@Transactional以及操作真实数据库

3、单测里时间相关的内容

笔者曾经在工作中遇到过一个极端case,一个CI平时都正常运行,有一次深夜发布, CI跑不过,后来经过第二天check才发现有前人在单测中取了当前时间,在业务逻辑中含有夜间逻辑(夜间消息不发),导致了CI无法通过。那么时间在单测中要如何处理呢?

在使用Mockito时,可以使用mock(Date.class)来模拟日期对象,然后使用when(date.getTime()).thenReturn(time)来设置日期对象的时间。

如果你使用了calendar.getInstance(),如何获取当前时间?Calendar.getInstance()是static方法,无法通过Mockito进行mock。需要引入powerMock,或者升级到mockito 4.x才能支持:

final类,static类等的单元测试

如第3点提到的calendar的例子,static类的mock需要mockito4.x的版本。否则就要引入powermock,powermock不兼容mockito3.x版本,不兼容mockito 4.x版本。由于老的应用引入了非常多的mockito3.x的版本,直接使用mockito4.x对final和static类进行mock需要排包。实践中看,JUnit、Mockito、Powermock三者之间的版本号有兼容性问题,可能会出现java.lang.NoSuchMethodError,需要根据实际的情况选择版本进行mock。

但是在新项目立项的时候,要确定好使用的mockito和junit版本,是否引入powermock等框架,确保环境稳定可用。老项目建议不要大规模改动mockito和powermock的版本,容易排包排到怀疑人生。

总结一下什么时候使用容器:

// 1. 使用PowerMockRunner

@RunWith(PowerMockRunner.class)

// 2.使用PandoraBootRunner, 启动pandora,使用tair,metaq等

@RunWith(PandoraBootRunner.class)

// 3. springboot启动,加入context上下文,可以直接获取bean

@SpringBootTest(classes = {TestApplication.class})

不要为了覆盖率测没意义的代码

比如toString,比如getter,setter,都是机器生成的代码,单测没意义。如果是为了整体测试覆盖率的提高,那么请在CI中排掉这部分包:

如何测试void方法

如果void方法内部造成了数据库的变更,比如insertPlan(Plan plan),并通过H2操作过数据库,那么可以验证数据库的条数变化等,校验void方法的正确性。

如果void方法调用了函数,可以通过verify验证方法得到调用次数:

userService.updateName(1L,"qiushuo");

verify(mockedUserRepository, times(1)).updateName(1L,"qiushuo");

如果void方法可能会造成抛出异常。

可以通过dothrow来 mock方法抛出的异常:

@Test(expected = InvalidParamException.class)

public void testUpdateNameThrowExceptionWhenIdNull() {

doThrow(new InvalidParamException())

.when(mockedUserRepository).updateName(null,anyString();

userService.updateName(null,"qiushuo");

}

使用 squaretest testme junit5 + Mockito

IDEA 安装 squaretest testme 插件

配置模板后 在你想要的生的单测的类 右键生成 test类

相关推荐
百事老饼干5 分钟前
Java[面试题]-真实面试
java·开发语言·面试
customer0812 分钟前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea
霍格沃兹测试开发学社测试人社区21 分钟前
软件测试学习笔记丨Flask操作数据库-数据库和表的管理
软件测试·笔记·测试开发·学习·flask
2402_8575893622 分钟前
SpringBoot框架:作业管理技术新解
java·spring boot·后端
HBryce2426 分钟前
缓存-基础概念
java·缓存
今天我又学废了37 分钟前
Scala学习记录,List
学习
一只爱打拳的程序猿41 分钟前
【Spring】更加简单的将对象存入Spring中并使用
java·后端·spring
杨荧42 分钟前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
minDuck44 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js