You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单元测试中Class Cast Exception问题排查与解决(Diffblue场景)

解决Mockito测试中的ClassCastException及参数匹配错误

问题根源

  1. 测试逻辑冗余且冲突:你的测试用例目标是验证「Dashboard不存在时抛出ResourceNotFoundException」,但代码在dashboardRepository.findById(id).orElseThrow()处就直接抛出异常了,根本不会执行到modelMapper.map方法。你给modelMapper设置的mock不仅多余,还因为第一个when(modelMapper.map((Object) any(), any())).thenReturn("Map")的匹配规则更宽泛(Mockito按顺序匹配,先匹配到这条规则),导致后续即使有更具体的匹配,也会先返回String,而方法需要返回DashboardGetDto,从而触发ClassCastException。
  2. Mockito参数匹配用法错误:强制转换any()为特定类型(比如(String) any()、(Class<DashboardGetDto>) any())是错误写法,会导致IDE报错「无法将类java.lang.Object转换为类org.mockito.ArgumentMatcher」——因为any()本身返回的是ArgumentMatcher实例,不能直接强制转为普通类型。

修复方案

方案1:精简测试用例(推荐)

既然测试场景是验证「Dashboard不存在时抛出异常」,完全不需要涉及modelMapper的mock,直接去掉所有无关代码即可:

void testGetDashboardById3() {
    // 模拟Repository返回空,触发异常
    when(dashboardRepository.findById(anyString())).thenReturn(Optional.empty());
    
    // 验证抛出指定异常
    assertThrows(ResourceNotFoundException.class, () -> dashboardServiceImpl.getDashboardById("42"));
    
    // 验证Repository方法被调用
    verify(dashboardRepository).findById(anyString());
    // 无需验证modelMapper,代码根本没执行到这一步
}

方案2:修正Mockito参数匹配写法(适用于需要mock modelMapper的场景)

如果是其他需要用到modelMapper的测试场景,要使用类型安全的匹配器:

  • 匹配字符串用anyString()
  • 匹配Class类型用any(Class.class)或eq(DashboardGetDto.class)(精确匹配时)

正确的mock写法示例:

// 匹配任意Object、任意Class的map调用
when(modelMapper.map(any(), any(Class.class))).thenReturn(dashboardGetDto);

// 或者精确匹配目标Class
when(modelMapper.map(any(), eq(DashboardGetDto.class))).thenReturn(dashboardGetDto);

额外说明

  • Mockito的mock规则按顺序匹配,宽泛的规则会优先触发,所以不要先设置宽泛mock再设置具体mock,否则具体规则不会生效。
  • 编写测试用例要紧扣核心场景:每个测试只验证一个逻辑点,避免添加无关mock代码,减少不必要的错误。

内容的提问来源于stack exchange,提问作者Saif Thaha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 05:15:37