前言
清代谴责小说家吴趼人在《痛史》中写道:“卷帙浩繁,望而生畏。”
意思是:“ 一部书的篇幅太长,让人看见就害怕。”编写单元测试用例也是如此,如果单元测试用例写起来又长又复杂,自然而然地会让人“望而生畏”,于是开始反感甚至于最终放弃。为了便于Java单元测试的推广,作者总结了十余种测试用例的简化方法,希望能够让大家编写单元测试用例时——“化繁为简、下笔如神”。
1. 简化模拟数据对象
1.1. 利用JSON反序列化简化数据对象赋值语句
利用JSON反序列化,可以简化大量的数据对象赋值语句。首先,加载JSON资源文件为JSON字符串;然后,通过JSON反序列化JSON字符串为数据对象;最后,用该数据对象来模拟类属性值、方法参数值和方法返回值。
原始用例:
List<UserCreateVO> userCreateList = new ArrayList<>();
UserCreateVO userCreate0 = new UserCreateVO();
userCreate0.setName("Changyi");
... // 约几十行
userCreateList.add(userCreate0);
UserCreateVO userCreate1 = new UserCreateVO();
userCreate1.setName("Tester");
... // 约几十行
userCreateList.add(userCreate1);
... // 约几十条
userService.batchCreate(userCreateList);
简化用例:
String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreateList.json");
List<UserCreateVO> userCreateList = JSON.parseArray(text, UserCreateVO.class);
userService.batchCreate(userCreateList);
1.2. 利用虚拟数据对象简化返回值模拟语句
有时候,模拟的方法返回值在测试方法内部并不发生修改,只是起到一个透传的作用而已。对于这种情况,我们只需要模拟一个对象实例,但并不关心其内部具体内容。所以,可以直接用虚拟数据对象替换真实数据对象,从而简化了返回值模拟语句。
被测代码:
@GetMapping("/get")
public ExampleResult<UserVO> getUser(@RequestParam(value = "userId", required = true) Long userId) {
UserVO user = userService.getUser(userId);
return ExampleResult.success(user);
}
原始用例:
// 模拟依赖方法
String path = RESOURCE_PATH + "testGetUser/";
String text = ResourceHelper.getResourceAsString(getClass(), path + "user.json");
UserVO user = JSON.parseObject(text, UserVO.class);
Mockito.doReturn(user).when(userService).getUser(user.getId());
// 调用测试方法
ExampleResult<UserVO> result = userController.getUser(user.getId());
Assert.assertEquals("结果编码不一致", ResultCode.SUCCESS.getCode(), result.getCode());
Assert.assertEquals("结果数据不一致", user, result.getData());
简化用例:
// 模拟依赖方法
Long userId = 12345L;
UserVO user = Mockito.mock(UserVO.class); // 也可以使用new UserVO()
Mockito.doReturn(user).when(userService).getUser(userId);
// 调用测试方法
ExampleResult<UserVO> result = userController.getUser(userId);
Assert.assertEquals("结果编码不一致", ResultCode.SUCCESS.getCode(), result.getCode());
Assert.assertSame("结果数据不一致", user, result.getData());
1.3. 利用虚拟数据对象简化参数值模拟语句
有时候,模拟的方法参数值在测试方法内部并不发生修改,只是起到一个透传的作用而已。对于这种情况,我们只需要模拟一个对象实例,但并不关心其内部具体内容。所以,可以直接用虚拟数据对象替换真实数据对象,从而简化参数值模拟语句。
被测代码:
@GetMapping("/create")
public ExampleResult<Void> createUser(@Valid @RequestBody UserCreateVO userCreate) {
userService.createUser(userCreate);
return ExampleResult.success();
}
原始用例:
// 调用测试方法
String path = RESOURCE_PATH + "testCreateUser/";
String text = ResourceHelper.getResourceAsString(getClass(), path + "userCreate.json");
UserCreateVO userCreate = JSON.parseObject(text, UserCreateVO.class);
ExampleResult<Void> result = userController.createUser(userCreate);
Assert.assertEquals("结果编码不一致", ResultCode.SUCCESS.getCode(), result.getCode());
// 验证依赖方法
Mockito.verify(userService).createUser(userCreate);
简化用例:
// 调用测试方法
UserCreateVO userCreate = Mockito.mock(UserCreateVO.class); // 也可以使用new UserCreateVO()
ExampleResult<Void> result = userController.createUser(u