@MockBean默认配置注入RestTemplate第二测试抛空指针问题咨询
问题根因
你的测试配置类存在明确的类型定义错误,是导致Mock重置后出现NPE的核心原因。
问题1:为什么@MockBean默认的MockReset.RESET行为没有正常生效?
默认的MockReset.RESET策略本身工作逻辑正常,它的作用是在每个测试方法执行前后重置mock对象的存根配置和调用记录,不会修改mock对象的内存地址。
你遇到的异常和mock策略无关:测试配置类里Bean的返回类型声明为ObjectNode,但实际返回的是WeatherServiceImpl实例,而ObjectNode是Jackson的final类,无法被Spring生成动态代理。当mock重置操作触发上下文的代理校验逻辑时,代理失效导致WeatherServiceImpl中持有的RestTemplate引用被清空,最终抛出NPE。
当你设置reset = MockReset.NONE时,跳过了mock重置触发的代理校验逻辑,错误的Bean定义没有被触发,所以测试可以临时正常运行,但这只是规避了问题,没有解决根本错误。
问题2:是否是我的测试搭建方式存在问题,导致默认的MockReset.RESET策略失效?
测试搭建的整体结构没有逻辑问题,唯一的问题就是测试配置类的Bean定义错误,和mock重置策略本身无关。
问题3:我的测试配置类是否存在错误?
存在明确的类型声明错误,你配置的WeatherService Bean的返回类型写错了,原本应该返回WeatherService类型,你误写成了ObjectNode:
错误代码:
@Bean @Primary public ObjectNode getWeatherService(RestTemplate restTemplate) { return new WeatherServiceImpl(restTemplate); }
修正后的代码:
@Bean @Primary public WeatherService getWeatherService(RestTemplate restTemplate) { return new WeatherServiceImpl(restTemplate); }
修正后你即使使用默认的MockReset.RESET策略,两个测试用例也能正常运行,不需要额外设置reset = MockReset.NONE。
额外优化建议
你在测试配置类中加@Primary定义WeatherService的Bean属于冗余配置,因为你的业务代码已经通过@Service注解注册了WeatherServiceImpl,直接删掉这个测试配置类,测试也可以正常运行。
内容的提问来源于stack exchange,提问作者BDF

