Kotlin中Mockito调用.thenThrow抛自定义异常提示受检异常无效如何解决
Checked exception is invalid for this method报错本质是Mockito遵循Java受检异常校验规则导致的:
Mockito会读取目标方法的字节码签名,若方法没有声明抛出对应受检异常,就不允许Mock时指定抛出该异常。
Kotlin没有强制受检异常声明的语法要求,你写的getHelp方法默认编译出的字节码签名里没有throws HelpNotFoundException的声明,因此Mockito校验不通过。
你猜测的两种方案都可以正常解决问题,适用场景不同:
方案1:业务方法加@Throws注解(更推荐)
在Service层getHelp方法上添加@Throws(HelpNotFoundException::class)注解:
@Throws(HelpNotFoundException::class) override fun getHelp(helpId: Long): Help { // 原有逻辑不变 }
这个注解会让Kotlin编译器在生成的字节码方法签名中添加对应异常的throws声明,符合Mockito的校验规则。
该方案的优势是明确了方法的异常契约,哪怕后续有Java代码调用该Service方法也能正确感知到可抛出的异常,属于规范性修改。
方案2:测试代码传入异常实例(无需修改业务代码)
把测试代码里的Mockito写法调整为直接传入构造好的异常实例,而非异常Class对象:
// 原来的写法 // Mockito.`when`(helpService.getHelp(helpId)).thenThrow(HelpNotFoundException::class.java) // 修改后的写法 Mockito.`when`(helpService.getHelp(helpId)).thenThrow(HelpNotFoundException(helpId))
Mockito处理传入异常实例的场景时,不会做严格的受检异常签名校验,会直接让Mock方法抛出该实例,绕过校验逻辑。
该方案适合不想改动业务代码、仅调整测试逻辑的场景,修改成本更低。
如果你们项目的异常规范允许,可将HelpNotFoundException改为继承RuntimeException的运行时异常,运行时异常不需要方法声明抛出,Mockito默认不会做校验,两种写法都不会报错。
内容的提问来源于stack exchange,提问作者basti394

