乐趣区

关于后端:Java单元测试及常用语句-京东物流技术团队

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 转载请注明起源

退出移动版