如何让单元测试覆盖率达到81%甚至以上(下)

发表于:2023-3-31 09:42

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

 作者:你可以叫我老白    来源:稀土掘金

  常用的 Mockito 方法
  Mockito的使用,一般有以下几种组合:参考链接
  ·do/when:包括doThrow(…).when(…)/doReturn(…).when(…)/doAnswer(…).when(…)
  · given/will:包括given(…).willReturn(…)/given(…).willAnswer(…)
  · when/then: 包括when(…).thenReturn(…)/when(…).thenAnswer(…)/when(…).thenThrow(…)
  Mockito 的多种匹配函数,部分如下:
  四:常见问题
  1.我自己明明已经模拟了方法,为什么还无法走通?
  mock中模拟Mockito.when( 对象.方法名() ).thenReturn( 自定义结果 ),方法名()中参数有的人会使用实际的参数,这样会导致模拟是无法找到正确的结果。所以我们需要使用Mockito.any()去替代,让mock自己去模拟。以及thenReturn中返回的值要符合业务逻辑才能保证业务能够走通。参考:
  Mockito.when(deviceFeignService.queryDeviceInfoByDeviceCode(Mockito.any())).thenReturn(deviceExtDataEntity);
  2.为什么有时候使用Mockito.any()模拟方法时会报错?
  这个是因为有时模拟时的参数类型不正确的原因,参考:Mockito 的多种匹配函数。如果还是报错,建议使用准确值,比如参数为int=1。但就会出现问题一无法返回结果。有知道的大佬可以评论。
  3.有时候需要启动参数或者需要连接真实配置(一般junit需要同适用)怎么办?
  代表启动参数或者是使用的某个配置文件,注解和代码选择其中之一。参考下图
  @ActiveProfiles("baseline")
  或者
  static {
  System.setProperty("env", "baseline");
  }
  4.有的代码中需要判断常量值才能继续往下走,如何模拟?
  说实话,这个问题很恶心,麻烦了很久。后来查到可以使用映射测试模拟类,参考:
  ReflectionTestUtils.setField()方法接受三个参数:要设置属性值的对象、属性名称和属性值。通过这个方法,我们可以方便地通过反射去设置一个对象的私有变量值,从而在测试代码中控制这个对象的行为。需要注意的是,如果想要通过ReflectionTestUtils.setField()方法修改的变量是静态的,那么第一个参数应为null,因为静态变量属于类级别的而不是实例级别的。
  ReflectionTestUtils.setField(deviceServiceImpl, "deviceTypeCodes", "1000");
  5. 代码比较老旧,或者有的需要通过连接redis等组件返回结果,业务才能继续往下走?
  因为返回的对象无法正常new,我们可以通过Mockito.mock()方法可以创建类或接口的模拟对象。比如:
  // redisTemplate写法:
  ListOperations<String, String> listOperations = Mockito.mock(ListOperations.class);
  Mockito.when(redisTemplate.opsForList()).thenReturn(listOperations);
  Mockito.when(listOperations.size(Mockito.any())).thenReturn(10L);
  //JDBC写法:
  你可以直接带@Before方法中去先初始化模拟:
  @Mock
  DbUtils openCustomDbUtils;
  @Mock
  DbUtils newCustomDbUtils;
  @InjectMocks
  NluDataDao test;
  @Before
  public void setUp() {
      MockitoAnnotations.openMocks(this);
      getTestByOne();
  }
  private void getTestByOne() {
      try {
          Connection conn = Mockito.mock(Connection.class);
          conn.setAutoCommit(true);
          PreparedStatement ps = Mockito.mock(PreparedStatement.class);
          ResultSet rs = Mockito.mock(ResultSet.class);
          ps.setString(1, "1");
          int i = ps.executeUpdate();
          PowerMockito.when(conn.prepareStatement(Mockito.any())).thenReturn(ps);
          PowerMockito.when(ps.getGeneratedKeys()).thenReturn(rs);
          PowerMockito.when(ps.executeUpdate()).thenReturn(1);
          PowerMockito.when(openCustomDbUtils.getConn()).thenReturn(conn);
      } catch (Exception e) {
      }
  }
  @Test
  public void testLoadAllAppVOs() {
      // Setup
      getTestByOne();
      getTestByFour();
      // Run the test
     test.loadAllAppVOs();
  }
  test.loadAllAppVOs()方法代码:
  6. 有得使用了一些框架或者工具类去查询数据,比如mybatiesPlus。代码走不下去怎么办?
  其实这也是我为什么讨厌有的人炫技的原因之一。下列报错:
  解决方法:
  Config config = new Config();
  EntityHelper.initEntityNameMap(IotStrategyTriggerSensorDO.class,config);
  jar包选择:
  import tk.mybatis.mapper.entity.Config;
  import tk.mybatis.mapper.mapperhelper.EntityHelper;
  五:小技巧
  有的工程师写完以后想看一下自己覆盖率的多少,以idea为例有两种方法。(方法2通用)
  1.
  2.第二种相当于执行mvn test命令。有的时候测试报告和idea扫描的会有不同,需要以自己环境为准。
  idea插件:Squaretest,帮助自动生成单元测试类。选择第二种使用。
  注意:生成后的需要修改,别忘了上面碰到的问题。
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

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

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

沪ICP备05003035号

沪公网安备 31010102002173号