JUnit测试移除@SpringBootTest注解抛出NullPointerException原因及必要性问询
问题解答
空指针异常的触发原因
你的ExceptionInterceptor继承了Spring MVC提供的ResponseEntityExceptionHandler基类,这个基类内部包含多个需要Spring容器注入的依赖属性(比如消息转换器messageConverters、内容协商管理器contentNegotiationManager等),这些属性只有在Bean被Spring托管、完成上下文初始化流程时才会被赋值,手动实例化/Mockito直接实例化的对象中,这些属性默认都是null。
当你移除@SpringBootTest注解时:
- 测试仅通过
MockitoJUnitRunner运行,Mockito会自行实例化ExceptionInterceptor的Spy对象,该实例没有经过Spring的初始化流程,父类的所有依赖属性都是null - 你声明的
handleAysUserProvisException方法被final修饰,Mockito默认无法代理final方法,调用该方法时会触发父类的隐式校验/处理逻辑,用到了null的依赖属性,就抛出了空指针。
当你添加@SpringBootTest注解时:
- Spring会启动应用上下文,扫描到标注了
@ControllerAdvice的ExceptionInterceptor,将它实例化为Spring托管的Bean,自动完成父类所有依赖属性的注入 - 此时你对该Bean做Spy增强,所有依赖都是有效值,自然不会触发空指针。
@SpringBootTest在当前场景的必要性
严格来说,你当前的测试场景(仅验证自定义异常处理方法的返回值逻辑)其实不需要用到@SpringBootTest,启动完整Spring上下文会大大增加测试耗时。你可以通过以下改造去掉该注解:
- 移除
handleAysUserProvisException方法的final修饰符,让Mockito可以正常代理Spy对象的方法 - 如果你的其他异常处理逻辑没有用到
ResponseEntityExceptionHandler提供的默认异常处理能力,也可以直接去掉继承关系,避免依赖Spring注入的属性 - 直接实例化
ExceptionInterceptor对象做测试,不需要Spy/Mock相关的注解
内容的提问来源于stack exchange,提问作者qjonn
相关产品推荐
相关产品推荐

