浅谈SpringContext的单元测试写法

发表于:2022-4-18 09:49

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ShowMaker    来源:稀土掘金

  近期在为公司的旧代码写单元测试的时候,发现代码中有大量的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实现默认的返回。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号