Guava Cache异常未被捕获?Mockito测试报错求助
Guava Cache异常未捕获问题排查
问题场景
使用Guava Cache时,预期缓存加载失败时抛出自定义DependencyException,但测试触发了Mockito异常,自定义异常完全未被捕获,即使尝试捕获Throwable也无效。
代码片段
缓存设置
CacheLoader<String, Set<String>> loader = new CacheLoader<>() { public Set<String> load(String s) { return privateFunction(s); } }; this.cache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterWrite(5, TimeUnit.MINUTES) .build(loader);
业务实现
public Set<String> getTeamIdsForEmployee(String employeeAlias) { try { return this.cache.get(employeeAlias); } catch (ExecutionException e) { throw new DependencyException( "message", e); } }
测试代码
@Test(expectedExceptions = DependencyException.class) public void testGetTeamIdsForEmployeeCacheException() { doThrow(new ExecutionException("Test exception", new Exception())) .when(thing).privateFunction(eq("SAMPLE")); myClass.callCache("SAMPLE"); }
测试报错信息
[testng] 期望捕获类型为com.amazon.ampspermissionsservice.exceptions.DependencyException的异常,但实际得到org.mockito.exceptions.base.MockitoException: [testng] 该方法不能抛出受检异常! [testng] 无效异常:java.util.concurrent.ExecutionException
问题原因
核心是Mockito的受检异常限制:
privateFunction方法未声明抛出ExecutionException(受检异常),Mockito不允许强制给未声明受检异常的方法抛出受检异常;- 测试代码尝试让
privateFunction抛出ExecutionException时,Mockito直接抛出MockitoException打断流程,程序根本没走到cache.get()的try-catch逻辑,自然不会触发DependencyException。
解决方案
方案1:模拟非受检异常
如果privateFunction本身不声明抛出受检异常,改为模拟抛出RuntimeException子类,Guava Cache会自动将其包装为ExecutionException,进入catch块后转换为自定义异常:
@Test(expectedExceptions = DependencyException.class) public void testGetTeamIdsForEmployeeCacheException() { // 模拟抛出非受检异常 doThrow(new RuntimeException("Test exception")) .when(thing).privateFunction(eq("SAMPLE")); myClass.callCache("SAMPLE"); }
方案2:修改方法签名并模拟合法受检异常
如果privateFunction实际可能抛出受检异常,先修改其方法签名声明抛出对应异常,再模拟抛出该异常:
// 修改privateFunction的方法签名 private Set<String> privateFunction(String s) throws Exception { // 原有业务逻辑 } // 测试代码调整 @Test(expectedExceptions = DependencyException.class) public void testGetTeamIdsForEmployeeCacheException() { doThrow(new Exception("Test exception")) .when(thing).privateFunction(eq("SAMPLE")); myClass.callCache("SAMPLE"); }
核心逻辑说明
ExecutionException是Guava Cache用来包装CacheLoader.load()方法抛出异常的容器,不应由业务方法直接抛出。正确流程是:业务方法抛出异常 → Guava Cache包装为ExecutionException → 业务代码捕获并转换为自定义异常。
内容的提问来源于stack exchange,提问作者alex.weavers
相关产品推荐
相关产品推荐

