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类

相关推荐
拥抱AGI几秒前
我说大模型微调没啥技术含量,谁赞成谁反对?
人工智能·学习·语言模型·大模型学习·大模型入门·大模型教程
+码农快讯+4 分钟前
Git入门学习(1)
git·学习·elasticsearch
掐指一算乀缺钱18 分钟前
SpringBoot 数据库表结构文档生成
java·数据库·spring boot·后端·spring
MowenPan199523 分钟前
高等数学 3.5 函数的极值与最大值最小值
笔记·学习·高等数学
晚睡早起₍˄·͈༝·͈˄*₎◞ ̑̑23 分钟前
苍穹外卖学习笔记(七)
java·windows·笔记·学习·mybatis
就这个java爽!29 分钟前
JAVA网络编程【基于TCP和UDP协议】超详细!!!
java·开发语言·网络·tcp/ip·udp·eclipse·idea
一叶飘零_sweeeet33 分钟前
为什么 Feign 要用 HTTP 而不是 RPC?
java·网络协议·http·spring cloud·rpc·feign
百里与司空38 分钟前
学习CubeIDE——定时器开发
stm32·单片机·嵌入式硬件·学习
天下无贼!40 分钟前
2024年最新版Vue3学习笔记
前端·vue.js·笔记·学习·vue
懒洋洋大魔王1 小时前
7.Java高级编程 多线程
java·开发语言·jvm