您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
Java单元测试及常用语句
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
Java单元测试及常用语句
自猿其说Tech
2022-07-12
IP归属:未知
102880浏览
计算机编程
### 1 前言 编写Java单元测试用例,即把一段复杂的代码拆解成一系列简单的单元测试用例,并且无需启动服务,在短时间内测试代码中的处理逻辑。写好Java单元测试用例,其实就是把“复杂问题简单化,建单问题深入化“。 编写单元测试的好处: 1. 测试代码逻辑时,不需要启动整个应用。 2. 单元测试可以覆盖边界值 3. 提高原有代码的复用 4. 可以有效避免代码改动后,对原有逻辑的潜在影响 ### 2 准备环境 Mockito是目前最普遍的单元测试模拟框架。Mockito可以模拟应用中依赖的复杂对象,从而把测试对象和依赖对象隔离开。PowerMock为Mockito提供了扩展功能。为模拟静态方法,final类,和私有方法等。我们选择使用以Mockito为主,PowerMock为辅的框架来做单元测试。 #### 2.1 引入Mockito和PowerMock包,在pom.xml文件中加入以下依赖: ```java <properties> <powermock.version>2.0.9</powermock.version> </properties> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-core</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> ``` PowerMock目前最新版本为2.0.9【PowerMock链接】由于PowerMock包中已经包含了对应的Mockito和JUnit包,所以无需再单独引入。 ### 3 一些常用的mock语句 #### 3.1 模拟指定类的对象实例,用于模拟依赖对象(类成员) 在Spring中,这些成员对象通过@Autowire,@Resource,@Value等方式注入,可能涉及到环境配置或者依赖第三方接口。在单元测试中,不是我们关注的点,所以可以用mock模拟 ```java //方法一 Mockito.mock(OrderInfo.class); //方法二 @Mock private OrderInfo orderInfo; @Before public void setUp(){ MockitoAnnotations.initMocks(this); } ``` #### 3.2 定义被测试对象 把被测试服务类进行实例化 ```java @InjectMocks private ReceiveOrderServiceImpl receiveOrderService; ``` #### 3.3 模拟枚举类型/静态方法 需要把对应的模拟类放在@PrepareForTest中 ```java //必须添加@RunWith和@PrepareForTest在类前 @RunWith(PowerMockRunner.class) @PrepareForTest(CustomerCodeEnum.class) //在@Before中添加枚举mock @Before public void beforeTest() { mockStatic(CustomerCodeEnum.class); } ``` #### 3.4 模拟依赖方法 在模拟完依赖的参数和返回值后,可以利用Mockito功能,进行依赖方法的模拟。如果模拟对象还有方法调用,则需要模拟这些依赖对象的方法。 ```java /*** when.thenReturn 和 doReturn.when是两种实现方式 只有在使用@Spy时才会有区别 参考链接:https://www.imooc.com/wenda/detail/594190#id_653606 ***/ //模拟枚举的方法调用 when(CustomerCodeEnum.getCustomCodeByOrgId(anyInt())).thenReturn("021K0003"); //模拟依赖对象的依赖方法调用 doReturn(resultInfoDTO).when(orderInfoJosService).preDeliveryId(orderInfoDTO); ``` #### 3.5 模拟构造方法 PowerMock提供了对构造方法的模拟,但是需要把构造方法的类放在@PrepareForTest中 ```java //必须在@PrepareForTest中添加对应类 @PrepareForTest({CustomerCodeEnum.class, ReceiveOrderServiceImpl.class}) whenNew(OrderInfoDTO.class).withNoArguments().thenReturn(orderInfoDTO); ``` #### 3.6 验证方法调用次数 被测方法调用后,一些方法会出现调用多次或根据不同条件进行不同次数的调用。此时,可以根据验证方法调用次数,确定代码的有效性 ```java verify(orderInfoJosService,times(1)).preDeliveryId(orderInfoDTO); ``` #### 3.7 验证返回值 对于方法调用后的出参,我们会有一定的预期。所以,可以根据校验返回值是否符合预期,确保返回值的正确性 ```java Assert.assertEquals(result, "123"); ``` #### 3.8 验证异常对象 JUnit的@Test注解提供了一个expected属性,可以指定一个期望的异常类型,用于捕获异常并验证其异常类型。【注】:只能验证异常类型,不能验证异常信息。 ```java @Test(expected = BPLException.class) ``` ### 4 单测举例 下面是一个本地方法的单元测试用例,方法中调用了外部接口,并且其中包含了枚举值的使用。 源方法即需要单测方法: ![](//img1.jcloudcs.com/developer.jdcloud.com/6b510bbd-d777-4a18-b591-de9926c4f29620220712143351.png) 首先,是单元测试时一些必要的初始化: ![](//img1.jcloudcs.com/developer.jdcloud.com/97d1b4df-71de-4fed-a058-e482f11c967f20220712143359.png) #### 4.1 单测场景一(确定接口调用,并返回值正确) 通过verify方法来确定接口是否调用过,并且只调用过1次。 通过assert来确认返回值是否满足预期 ![](//img1.jcloudcs.com/developer.jdcloud.com/282a2aa6-e797-4297-aa60-7f39bac507c220220712143417.png) #### 4.2 单测场景二(必要异常是否抛出) 通过在@Test注解上加入expected属性,测试当接口返回值为空时,是否可以抛出异常 ![](//img1.jcloudcs.com/developer.jdcloud.com/a5e1c470-165d-4dfb-b079-8e49a9fb435e20220712143431.png) ### 4 总结 编写单元测试在开发中的地位举足轻重。在开发过程中,避免不了优化或重构历史代码。单元测试,在一定程度上可以帮助测试更新后逻辑,以及潜在调用链。另外也分享一些链接,希望可以帮助大家完成从0到1的搭建。 ### 5 参考资料 Java编程技巧之单元测试用例编写流程:https://mp.weixin.qq.com/s/hX_RIYs-nBnqVwdq5B4rhg powerMock的Git链接:https://github.com/powermock/powermock powerMock简介:https://www.baeldung.com/intro-to-powermock 避免Install的时候Skip test: https://maven.apache.org/plugins-archives/maven-surefire-plugin-2.12.4/examples/skipping-test.html ------------ ###### 自猿其说Tech-JDL京东物流技术与数据智能部 ###### 作者:牟佳义
原创文章,需联系作者,授权转载
上一篇:mysql 最大建议行数2000w,靠谱吗?
下一篇:当你对 redis 说你中意的女孩是 Mia
相关文章
Taro小程序跨端开发入门实战
Flutter For Web实践
配运基础数据缓存瘦身实践
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
本文将从Optional所解决的问题开始,逐层解剖,由浅入深,文中会出现Optioanl方法之间的对比,实践,误用情况分析,优缺点等。与大家一起,对这项Java8中的新特性,进行理解和深入。
01
Taro小程序跨端开发入门实战
为了让小程序开发更简单,更高效,我们采用 Taro 作为首选框架,我们将使用 Taro 的实践经验整理了出来,主要内容围绕着什么是 Taro,为什么用 Taro,以及 Taro 如何使用(正确使用的姿势),还有 Taro 背后的一些设计思想来进行展开,让大家能够对 Taro 有个完整的认识。
01
Flutter For Web实践
Flutter For Web 已经发布一年多时间,它的发布意味着我们可以真正地使用一套代码、一套资源部署整个大前端系统(包括:iOS、Android、Web)。渠道研发组经过一段时间的探索,使用Flutter For Web技术开发了移动端可视化编程平台—Flutter乐高,在这里希望和大家分享下使用Flutter For Web实践过程和踩坑实践
01
配运基础数据缓存瘦身实践
在基础数据的常规能力当中,数据的存取是最基础也是最重要的能力,为了整体提高数据的读取能力,缓存技术在基础数据的场景中得到了广泛的使用,下面会重点展示一下配运组近期针对数据缓存做的瘦身实践。
自猿其说Tech
文章数
426
阅读量
2149964
作者其他文章
01
深入JDK中的Optional
01
Taro小程序跨端开发入门实战
01
Flutter For Web实践
01
配运基础数据缓存瘦身实践
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号