浅谈SpringContext的单元测试写法
近期在为公司的旧代码写单元测试的时候,发现代码中有大量的Domain层代码使用了SpringContextUtil.getBean()这个方法,获取Sping中的Bean,这导致了普通的单元测试写法无法获取到这个对象,引发了空指针异常,导致单元测试失败,经过一番摸索,发现使用PowerMockito可以完美的解决问题。业务代码示例
校验某个字段是否已经和数据库中的字段的属性重复。
private void check(String code, String name) {
if (SpringContextUtils.getBean(FieldRepo.class).checkFieldExist(code, name, getDepartmentId()) > 0) {
throw new BusinessException("字段名称或code重复");
}
}
单元测试示例
单元测试的类名上要加@PrepareForTest(SpringContextUtils.class)注解。
写法一
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void createCheckAndProcessTest1() {
PowerMockito.mockStatic(SpringContextUtils.class);
PowerMockito.when(SpringContextUtils.getBean(FieldRepo.class)).thenReturn(fieldRepo());
PowerMockito.when(fieldRepo.checkFieldExist(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(1);
FieldBO fieldBO = new FieldBO();
thrown.expect(BusinessException.class);
thrown.expectMessage("字段名称或code重复");
fieldBO.createCheckAndProcess();
}
public FieldRepo fieldRepo() {
return new FieldRepo(){
@Override
public int countList(FieldPageInfoBO param) {
return 0;
}
@Override
public List<FieldBO> queryList(FieldPageInfoBO param) {
return null;
}
@Override
public int checkFieldExist(String code, String name, Long departmentId) {
return 0;
}
...
}
}
这种写法有一种弊端,在Mock FieldRepo这个对象的时候,采用了新建对象的方式,又由于这个对象是一个接口类,一旦接口发生变更,单元测试这里的方法也必须随之修改,不然就会导致项目编译错误,引起单元测试失败。不是最优的写法,后来经过笔者摸索,找到了另一种更优美的写法。
写法二
@Mock
FieldRepo fieldRepo;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void createCheckAndProcessTest1() {
PowerMockito.mockStatic(SpringContextUtils.class);
PowerMockito.when(SpringContextUtils.getBean(FieldRepo.class)).thenReturn(fieldRepo);
PowerMockito.when(fieldRepo.checkFieldExist(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(1);
FieldBO fieldBO = new FieldBO();
thrown.expect(BusinessException.class);
thrown.expectMessage("字段名称或code重复");
fieldBO.createCheckAndProcess();
}
直接使用@Mock注解来mock这个FieldRepo对象,实现了与接口方法具体实现的解耦,这样无论FieldRepo怎么变动都不会影响单元测试,且Mock通过代理可以为FieldRepo实现默认的返回。
页:
[1]