Spring Boot Controller catch块JUnit5测试覆盖及Mockito异常报错解决
问题根源
你遇到的报错是Mockito的固有规则限制:如果被Mock的方法本身没有在方法签名上声明抛出对应的已检查异常(Checked Exception),就无法通过thenThrow抛出这类异常,java.lang.Exception属于已检查异常,因此触发了报错。
你Controller的catch块捕获的是所有Exception类型,包含运行时异常和已检查异常,所以只要触发异常就能进入catch逻辑,不需要严格抛出Exception本身。
可行解决方案
方案1:抛出运行时异常(推荐,改动最小)
直接将测试代码中抛出的异常替换为运行时异常,运行时异常不需要方法提前声明,Mockito不会校验,同时也能正常进入Controller的catch块,完全满足测试需求:
// 把原来的thenThrow(new Exception())替换为下面的代码 Mockito.when(counterService.getAllCounters()).thenThrow(new RuntimeException("测试触发异常"));
方案2:修改业务方法签名(适合原本就需要抛出检查异常的场景)
如果确实需要抛出已检查异常,可以在counterService的getAllCounters方法签名上声明抛出Exception或者你自定义的已检查异常:
// service接口/实现类的方法签名修改 public ApartmentCounterListResponse getAllCounters() throws Exception { // 原有逻辑 }
修改后再用thenThrow(new Exception())就不会触发Mockito报错。
方案3:用doAnswer绕开校验(不推荐,仅做兜底方案)
如果既不想修改业务方法签名,又要抛出已检查异常,可以用doAnswer强行抛出异常,绕开Mockito的预检查:
Mockito.doAnswer(invocation -> { throw new Exception(); }).when(counterService).getAllCounters();
额外注意事项
你当前测试代码中存在拼写错误:counterServic少了末尾的e,应该为counterService,需要修正避免后续测试执行异常。
内容的提问来源于stack exchange,提问作者Sabu Shakya
相关产品推荐
相关产品推荐

