Spring Boot测试中BeanPostProcessor不处理@MockBean实例问题咨询
这不是Spring的预期行为,@MockBean生成的实例默认会完整走Spring Bean生命周期,也会被所有BeanPostProcessor处理,你遇到的问题是自身实现存在时序和容错处理的缺陷。
问题根因
- 异常被静默吞噬导致依赖失效
你在ManagedBeanInitializerBeanPostProcessor的setApplicationContext方法中,直接调用getBean获取ManagedComponent实例,一旦获取失败就直接吞掉异常,会导致managedComponent字段始终为null,后续所有AutowireComponent实现类都不会被注册。ManagedComponent作为BeanFactoryPostProcessor的实例化时机确实早于普通BeanPostProcessor,但在携带@MockBean的测试上下文中,Mockito相关后置处理器会调整部分Bean的初始化顺序,大概率是此时调用getBean触发了异常,被你直接忽略才出现问题。 - 依赖获取方式不稳定
通过ApplicationContextAware主动getBean的方式本身就无法保证依赖已经完全初始化完成,远不如Spring原生依赖注入机制可靠。
修复方案
方案1:调整自定义BeanPostProcessor的实现(推荐,从根源解决问题)
修改ManagedBeanInitializerBeanPostProcessor的代码,直接用@Autowired注入ManagedComponent,同时设置执行优先级保证晚于Mockito处理器运行:
@Component @Order(Ordered.LOWEST_PRECEDENCE) // 保证在Mockito相关后置处理器之后执行 public class ManagedBeanInitializerBeanPostProcessor implements BeanPostProcessor { @Autowired private ManagedComponent managedComponent; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof AutowireComponent) { managedComponent.addAutowireComponent((AutowireComponent) bean); } return bean; } }
方案2:测试侧临时兼容(无需修改业务代码)
如果不想调整业务代码,也可以在测试类中主动把Mock实例注册到ManagedComponent中:
@SpringBootTest @ContextConfiguration(classes = MainConfiguration.class) class ManagedComponentTests { @Autowired private ManagedComponent managedComponent; @MockBean private EmptyAutowireComponent emptyAutowireComponent; @PostConstruct void registerMockComponent() { managedComponent.addAutowireComponent(emptyAutowireComponent); } @Test void contextLoads() { managedComponent.invokeAll(); Mockito.verify(emptyAutowireComponent).invoke(); } }
内容的提问来源于stack exchange,提问作者Igor Chestnov
相关产品推荐
相关产品推荐

