1.Mockito
Mockito是GitHub上用于Java使用最广泛的Mock框架
Mockito核心解决的问题:不管是测试驱动开发,还是系统架构本身,都会带来的依赖结构复杂问题;单元测试做软件中的最小可测试单元,只应依当前单元的配置。 所有较大的系统都会有依赖复杂的问题。 此类问题就需要Mock框架来解决
2.快速上手
使用很简单一般分3部:
-
模拟外部依赖注入容器
-
执行单测
-
验证单测逻辑
2.1 SpringBoot环境
2.1.1 依赖配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${springboot.version}</version>
</dependency>
2.1.2 单测用例
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = LiveReportServiceTest.Config.class)
public class LiveReportServiceTest {
@Autowired
ILiveReportWriteService iLiveReportWriteService;
@MockBean
LiveReportMapper liveReportMapper;
@Test
public void updateLiveStatusTest() {
int num = iLiveReportWriteService.updateById(1L);
Assert.assertTrue(num >= 0);
}
@Configuration
static class Config {
@Bean
ILiveReportWriteService iLiveReportWriteService() {
return new LiveReportWriteServiceImpl();
}
}
}
@MockBean,在SpringBoot中通过@MockBean注解,就可以快速装在一个Mock的Bean了。
此方式通过非常简单的方式解决了系统层级之间单测的依赖,可以用在数据层和业务层,也可以用在业务层之间的多项依赖等依赖上的问题
直接执行:
image.png2.1.3 复杂单测用例
可以看到如果使用了SpringBoot,并且使用@MockBean可以快速解决依赖的问题。但是,Mock出的LiveReportMapper对象其实是个空壳,那么既然是mock就要知道如何通过mock的方式解决各种复杂逻辑
下面模拟2种复杂逻辑,Service层的单元测试mock依赖的另外一个Service类"InfoService" ,并且mock里面的2个方法
- 方法queryByLiveNo,任何调用都返回特定mock对象
- 方法removeById,任何调用都mock异常情况出现
下面看例子:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = LiveReportServiceTest.Config.class)
public class LiveReportServiceTest {
@Autowired
ILiveReportWriteService iLiveReportWriteService;
@Test
public void updateLiveStatusTest() {
int num = iLiveReportWriteService.updateById(1L);
Assert.assertTrue(num >= 0);
}
@Test(expected = Exception.class)
public void updateLiveStatusTest() {
iLiveReportWriteService.remove(1L);
}
@Configuration
static class Config {
@Bean
ILiveReportWriteService iLiveReportWriteService() {
return new LiveReportWriteServiceImpl();
}
@Bean
InfoService getLiveInfoService() throws LiveException {
LiveInfoPO liveInfoPO = new LiveInfoPO(111L);
liveInfoPO.setTime(System.currentTimeMillis());
InfoService mock = Mockito.mock(InfoService.class);
Mockito.when(mock.queryLiveInfoByLiveNo(Mockito.anyString())).thenReturn(liveInfoPO);
Mockito.when(mock.removeById(Mockito.anyString())).thenThrow(new Exception());
return mock;
}
}
}
-
假设iLiveReportWriteService.remove方法内部依赖了InfoService.removeById, 那么执行iLiveReportWriteService.remove方法时就会跑出异常
-
假设iLiveReportWriteService.updateById方法内部依赖了InfoService.queryLiveInfoByLiveNo,那么执行InfoService.queryLiveInfoByLiveNo方法时就会返回111的id
2.2 非SpringBoot环境
如果没有SpringBoot环境的Starter,可以直接使用Mockito。 除了@MockBean不能使用其他功能不受影响,参考上面例子
2.2.1 依赖配置
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
</dependency>
更多用法参考Mockito官方文档,此处不做赘述
网友评论