Mockito是用于单元测试的模拟框架,用来模拟一些不方便创建的对象,第三方服务的返回值等。关于Mockito的所有用法请看: https://javadoc.io/doc/org.mockito/mockito-core#,本文主要讲Mochito如何用于单元测试。
本文实战基于SpringBoot 2.3.1.RELEASE版本,该版本已经集成了Mockito 3.3.3版本。MVC项目等请自己引入依赖包。
首先介绍下Mockito的一些使用方式。
Mockito.when().thenReturn()和Mockito.when().thenThrow(),可以理解为当进行某个操作时然后返回某个对象或者抛出某个异常。其中,thenReturn()参数可以为可变参数列,意思是第一次到第n次调用返回的对象。
anyInt(), anyString()等ArgumentMatchers中的静态方法,为参数匹配,用于方法中的参数表示任何int值(anyInt())/任何字符串(anyString())。
简单示例:示例中mockedList.get(),传入任何int类型都会得到"element"。
@Test
public void testArgumentMatchers() {
List mockedList = mock(List.class);
//get(any int num) 校验参数匹配
when(mockedList.get(anyInt())).thenReturn("element");
System.out.println(mockedList.get(999));
// System.out.println(mockedList.add("mockedList.get(999)"));
// verify(mockedList).add(argThat((ArgumentMatcher<String>) s -> s.length() > 5));
}
使用Mockito进行单元测试:
Service代码:
@Override
public void findByName(String name) {
User user = userRepository.findFirstByName(name);
if (Objects.isNull(user)) {
System.out.println("未查询到用户信息");
} else {
Province province = user.getProvince();
System.out.println(Objects.isNull(province));
System.out.println(province.getName());
}
}
单元测试方法代码:
@Test
public void testFindByName() {
User user = new User();
user.setName("测试用户");
user.setAge(28);
user.setProvinceId(UUID.randomUUID().toString());
Province province = new Province();
province.setId(user.getProvinceId());
province.setName("安徽省");
user.setProvince(province);
//当传入任何根据字符串(用户名)查找时第一次返回null, 第二次返回user
when(userRepository.findFirstByName(anyString())).thenReturn(null, user);
userService.findByName("测试");
userService.findByName("测试");
userService.findByName("测试");
}
执行结果:
从结果来看:当when()方法执行次数超过thenReturn()返回值的个数时,超过的次数以最后一个返回值为准。
代码覆盖率报告:由图可见,if和else的代码都执行到了,和单独执行一个条件相比,提高了代码覆盖率。