1 前言
编写 Java 单元测试用例,即把一段简单的代码拆解成一系列简略的单元测试用例,并且无需启动服务,在短时间内测试代码中的解决逻辑。写好 Java 单元测试用例,其实就是把“简单问题简单化,建单问题深刻化“。在编写的过程中,咱们也能够对本人的代码进行一个二次查看。
以下是我总结的一些编写单元测试的益处:
1. 测试代码逻辑时,不须要启动整个利用。
2. 单元测试能够笼罩边界值
3. 进步原有代码的复用
4. 能够无效防止代码改变后,对原有逻辑的潜在影响
2 筹备环境
Mockito 是目前最广泛的单元测试模仿框架。Mockito 能够模仿利用中依赖的简单对象,从而把测试对象和依赖对象隔离开。PowerMock 为 Mockito 提供了扩大性能。为模仿静态方法,final 类,和公有办法等。咱们抉择应用以 Mockito 为主,PowerMock 为辅的框架来做单元测试。
2.1 引入 Mockito 和 PowerMock 包,在 pom.xml 文件中退出以下依赖:
<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 模仿
// 办法一
Mockito.mock(OrderInfo.class);
// 办法二
@Mock
private OrderInfo orderInfo;
@Before
public void setUp(){MockitoAnnotations.initMocks(this);
}
3.2 定义被测试对象
把被测试服务类进行实例化
@InjectMocks
private OrderServiceImpl orderService;
3.3 模仿枚举类型 / 静态方法
须要把对应的模仿类放在 @PrepareForTest 中
// 必须增加 @RunWith 和 @PrepareForTest 在类前
@RunWith(PowerMockRunner.class)
@PrepareForTest(OrderTypeEnum.class)
// 在 @Before 中增加枚举 mock
@Before
public void beforeTest() {mockStatic(OrderTypeEnum.class);
}
3.4 模仿依赖办法
在模仿完依赖的参数和返回值后,能够利用 Mockito 性能,进行依赖办法的模仿。如果模仿对象还有办法调用,则须要模仿这些依赖对象的办法。
/***
when.thenReturn 和 doReturn.when 是两种实现形式
只有在应用 @Spy 时才会有区别
参考链接:https://www.imooc.com/wenda/detail/594190#id_653606
***/
// 模仿枚举的办法调用
when(OrderTypeEnum.getByValue(anyInt())).thenReturn(100);
// 模仿依赖对象的依赖办法调用
doReturn(resultInfoDTO).when(orderInfoService).getLastOrderInfo(orderInfoDTO);
3.5 模仿构造方法
PowerMock 提供了对构造方法的模仿,然而须要把构造方法的类放在 @PrepareForTest 中
// 必须在 @PrepareForTest 中增加对应类
@PrepareForTest({OrderTypeEnum.class, OrderServiceImpl.class})
whenNew(OrderInfoDTO.class).withNoArguments().thenReturn(orderInfoDTO);
3.6 验证办法调用次数
被测办法调用后,一些办法会呈现调用屡次或依据不同条件进行不同次数的调用。此时,能够依据验证办法调用次数,确定代码的有效性
verify(orderInfoService,times(1)).getLastOrderInfo(orderInfoDTO);
3.7 验证返回值
对于办法调用后的出参,咱们会有肯定的预期。所以,能够依据校验返回值是否合乎预期,确保返回值的正确性
Assert.assertEquals(result, "123");
3.8 验证异样对象
JUnit 的 @Test 注解提供了一个 expected 属性,能够指定一个冀望的异样类型,用于捕捉异样并验证其异样类型。【注】:只能验证异样类型,不能验证异样信息。
@Test(expected = BPLException.class)
4 单测举例
上面是一个本地办法的单元测试用例,办法中调用了内部接口,并且其中蕴含了枚举值的应用。
源办法即须要单测办法:
首先,是单元测试时一些 必要的初始化:
4.1 单测场景一(确定接口调用,并返回值正确):
通过 verify 办法来确定接口是否调用过,并且只调用过 1 次。
通过 assert 来确认返回值是否满足预期
4.2 单测场景二(必要异样是否抛出):
通过在 @Test 注解上退出 expected 属性,测试当接口返回值为空时,是否能够抛出异样
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 转载请注明起源