SpringBootTest用ContextHierarchy缺失ObjectPostProcessor Bean问题求助
SpringBootTest ContextHierarchy 配置问题分析
让我们一步步拆解你遇到的问题:
1. ContextHierarchy 父子上下文的核心机制
首先要明确,@ContextHierarchy的作用是创建父子层级的Spring上下文:
- 你写的第一个
@ContextConfiguration会被作为父上下文,第二个作为子上下文 - 子上下文可以继承并访问父上下文里的Bean,但父上下文完全看不到子上下文的Bean
- 每个层级的上下文是独立初始化的,自动配置的触发逻辑也会各自处理
2. 拆分配置时抛出异常的原因
当你把DatabaseTestConfiguration和OverridingTestConfiguration拆分成两个层级时,问题出在上下文的依赖关系上:
- 父上下文只加载了
DatabaseTestConfiguration,大概率没有触发Spring Security相关的自动配置(毕竟这个配置是数据库相关的),所以父上下文里不存在ObjectPostProcessor这个Bean - 而
OverridingTestConfiguration里应该包含了Spring Security的配置(比如继承了WebSecurityConfigurerAdapter的类),当子上下文初始化这个配置时,WebSecurityConfigurerAdapter的setApplicationContext方法会尝试从当前上下文获取ObjectPostProcessor - 但子上下文本身也没有触发对应的Security自动配置(或者配置类没满足自动配置的条件),加上父上下文也没有这个Bean,就会抛出
NoSuchBeanDefinitionException - 因为上下文初始化失败了,自然也就无法被缓存
3. 合并配置时能缓存但包含额外Bean的原因
当你把两个配置合并到同一个@ContextConfiguration里时:
- 这时候不会创建父子上下文,而是一个单一的完整上下文
- Spring Boot的自动配置会正常触发,包括Security相关的自动配置,会自动创建
ObjectPostProcessorBean,所以上下文能顺利初始化 - SpringBootTest的上下文缓存是基于当前上下文的所有配置(包括两个配置类)生成的哈希值来判断的,所以这个包含了
OverridingTestConfiguration所有Bean的上下文会被缓存下来 - 但这不符合你想要的「缓存只包含数据库的上下文,子上下文覆盖Bean」的需求
可能的解决方案
如果想实现「缓存数据库上下文+子上下文覆盖Bean」的目标,可以试试这些思路:
- 在父上下文引入必要的自动配置:在
DatabaseTestConfiguration上加上@Import或者@EnableAutoConfiguration来引入Security相关的自动配置,确保父上下文包含ObjectPostProcessor,但这样父上下文会多出不必要的Bean - 在子上下文显式声明Bean:在
OverridingTestConfiguration里手动定义ObjectPostProcessorBean,让子上下文能找到它 - 放弃ContextHierarchy,改用@TestConfiguration:用
@TestConfiguration来定义需要覆盖的Bean,配合@SpringBootTest使用,这样整个上下文可以正常缓存,同时实现Bean的覆盖(Spring Boot会优先加载测试类里的@TestConfiguration)
内容的提问来源于stack exchange,提问作者Михаил Леонтьев
相关产品推荐
相关产品推荐

