Java单元测试中如何正确mock Arrays.asList相关方法调用?
问题解决:Mockito打桩
Arrays.asList(Locale.getISOCountries()).contains()报错 错误原因
when()方法仅支持对Mockito生成的Mock对象的方法调用进行打桩,Arrays.asList(Locale.getISOCountries())返回的是JDK原生的ArrayList实例,不是Mock对象,调用其contains()方法时会直接执行真实逻辑,Mockito无法捕获该调用作为打桩匹配条件,导致返回值类型匹配混乱,触发WrongTypeOfReturnValue异常。Locale.getISOCountries()是静态方法,@Mock Locale locale是对Locale实例对象的Mock,和静态方法无关,所以不会生效。doReturn(true).when(Arrays.asList(Locale.getISOCountries()).contains(countryCode))写法不符合Mockito语法规范:doReturn.when()的参数要求传入Mock对象本身,而非方法调用结果。
解决方案
方案1:直接使用真实合法的国家码(最推荐)
JDK返回的ISO国家码列表是固定的,直接传入真实存在的国家码(如CN、US),contains()方法本身就会返回true,无需额外打桩:
// 示例:直接使用合法国家码测试,无需打桩 String testCountryCode = "CN"; // 执行业务逻辑即可
方案2:封装逻辑后Mock自定义方法
如果需要支持自定义国家列表,将国家码获取逻辑抽为独立的工具类方法,再对自定义方法打桩:
- 封装工具类:
public class CountryHelper { public List<String> getAllISOCountries() { return Arrays.asList(Locale.getISOCountries()); } }
- 单元测试中打桩:
@Mock private CountryHelper countryHelper; @Test void testCountryValid() { String testCode = "TEST"; when(countryHelper.getAllISOCountries()).thenReturn(List.of(testCode)); // 后续执行业务逻辑即可 }
方案3:Mock静态方法(不推荐)
如果不想修改原有业务代码,可以引入mockito-inline依赖,直接MockLocale的静态方法:
try (MockedStatic<Locale> mockedLocale = Mockito.mockStatic(Locale.class)) { mockedLocale.when(Locale::getISOCountries).thenReturn(new String[]{"TEST"}); // 执行业务逻辑 }
该方案会降低测试执行速度,且容易引发上下文污染问题,非必要不建议使用。
内容的提问来源于stack exchange,提问作者user16979464
相关产品推荐
相关产品推荐

