单元测试中Class Cast Exception问题排查与解决(Diffblue场景)
解决Mockito测试中的ClassCastException及参数匹配错误
问题根源
- 测试逻辑冗余且冲突:你的测试用例目标是验证「Dashboard不存在时抛出
ResourceNotFoundException」,但代码在dashboardRepository.findById(id).orElseThrow()处就直接抛出异常了,根本不会执行到modelMapper.map方法。你给modelMapper设置的mock不仅多余,还因为第一个when(modelMapper.map((Object) any(), any())).thenReturn("Map")的匹配规则更宽泛(Mockito按顺序匹配,先匹配到这条规则),导致后续即使有更具体的匹配,也会先返回String,而方法需要返回DashboardGetDto,从而触发ClassCastException。 - 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
相关产品推荐
相关产品推荐

