仅在IntelliJ Debugger中触发Mockito Unfinished Stubbing Exception的原因排查
为什么仅在IntelliJ调试Mockito Mock对象时会抛出UnfinishedStubbingException?
这个问题我之前排查过好几次,不是Mockito的Bug,而是调试器和Mockito内部校验机制交互时的典型认知盲区,咱们一步步拆解原因和解决办法:
核心原因分析
调试器的自动toString()调用
IntelliJ调试面板在显示变量时,默认会自动调用对象的toString()方法来生成友好的显示文本。而Mockito的Mock对象内部有一套严格的Stubbing状态校验——当你还在编写Stubbing代码(比如when(repo.findById(1L)).thenReturn(...))的过程中,如果调试器此时触发了Mock对象的toString(),Mockito会认为你正在进行的Stubbing操作未完成,直接抛出UnfinishedStubbingException。直接运行测试时无异常的原因
直接运行测试时,程序不会触发调试器的变量监视逻辑,也就不会主动调用Mock对象的toString()。只要你的Stubbing代码最终是完整执行的,Mockito就不会抛出异常,测试自然能正常通过。
解决办法
针对这个场景,有几个实用的解决方式:
- 调整断点位置:不要在Stubbing代码的中间(比如
when(...)和thenReturn(...)之间)设置断点,把断点放在Stubbing代码全部执行完成之后的位置,避免调试器在Stubbing未完成时访问Mock对象。 - 自定义Mock的toString():提前给Mock对象Stub好
toString()方法,绕过Mockito的默认校验逻辑,比如:@Mock private CustomerChoiceRepository customerChoiceRepository; @BeforeEach void setUp() { // 先Stub toString(),避免调试时触发异常 when(customerChoiceRepository.toString()).thenReturn("Mocked CustomerChoiceRepository"); // 再Stub其他业务方法 when(customerChoiceRepository.findById(anyLong())).thenReturn(Optional.empty()); } - 修改IntelliJ调试设置:打开
Settings -> Build, Execution, Deployment -> Debugger -> Data Views -> Java,取消勾选「Enable toString() object view」,或者在下方的「Exclude classes」中添加com.item.repository.jpa.CustomerChoiceRepository,让调试器不再自动调用该类Mock对象的toString()。
总结
这本质上是调试器的自动变量展示行为和Mockito的Stubbing状态校验规则冲突导致的,只要理解了两者的交互逻辑,调整代码或设置就能轻松解决。
内容的提问来源于stack exchange,提问作者ng.newbie
相关产品推荐
相关产品推荐

