为何@Nested测试类无法读取@TestPropertySource的覆盖配置?
Spring Boot嵌套集成测试@TestPropertySource不生效的原因
问题重现
你编写的测试代码如下:
@TestPropertySource(properties = {"spring.application.environment=dev"}) @SpringBootTest class IntegrationTest { @Autowired PropertyConfig propertyConfig; @Nested @SpringBootTest @TestPropertySource(properties = {"spring.application.environment=dev", "spring.application.property=example"}) class ServerLoadConfiguration { @Test void exampleTest() { String someProperty = propertyConfig.getSomeProperty(); // 获取到的是旧值,不是覆盖后的example .... } } }
问题:嵌套类ServerLoadConfiguration的exampleTest中,读取到的属性是默认值而非@TestPropertySource指定的覆盖值,但把该@TestPropertySource移到外层IntegrationTest类上时,嵌套类就能读到覆盖值。
原因解析
这核心是Spring Boot测试上下文的创建规则和嵌套类的bean作用域问题:
- 外层
IntegrationTest标注了@SpringBootTest,会初始化一个独立的Spring上下文,加载外层的@TestPropertySource配置,并把propertyConfig注入到外层类的字段中。 - 嵌套类
ServerLoadConfiguration也标注了@SpringBootTest,这会触发创建另一个全新的独立上下文,这个上下文确实会加载嵌套类自己的@TestPropertySource配置。但你在exampleTest里调用的propertyConfig是外层类已经注入好的实例——它属于外层的旧上下文,和嵌套类的新上下文完全无关,自然读不到新的属性值。 - 当你把
@TestPropertySource移到外层类时,外层上下文会直接加载覆盖后的属性,嵌套类的@SpringBootTest默认会继承外层的测试配置(包括属性),所以此时无论是复用上下文还是新创建的上下文,都会使用外层的属性配置,自然能读到覆盖值。
解决办法
有两种常用的修复方式:
- 把
propertyConfig注入到嵌套类中:在ServerLoadConfiguration类里重新添加@Autowired PropertyConfig propertyConfig;,这样会从嵌套类的新上下文中获取bean实例,就能读到覆盖后的属性。 - 去掉嵌套类上的
@SpringBootTest:这样嵌套类会直接复用外层的上下文,此时如果嵌套类有自己的@TestPropertySource,会在原有上下文的基础上覆盖属性,也能读到正确的值。
内容的提问来源于stack exchange,提问作者nixadet464
相关产品推荐
相关产品推荐

