Spring测试中@ConfigurationProperties绑定失败,如何加载InfluxDB配置?
问题场景
我在编写集成测试时,尝试从application.yml、application-test.yml、application-integrationTest.yml这些配置文件里加载InfluxDB的配置属性,测试类代码是这样的:
@RunWith(SpringRunner.class) @EnableConfigurationProperties(InfluxDBProperties.class) public class StupidRepoIntegrationTest { @Autowired public InfluxDBProperties properties; @Test public void test() { System.out.println(stringify.apply(properties)); } static Function<InfluxDBProperties, String> stringify = new Function<InfluxDBProperties, String>() { @Override public String apply(InfluxDBProperties influxDbProperties) { StringBuilder sb = new StringBuilder("InfluxDBProperties: ["); sb.append("Url=").append(influxDbProperties.getUrl()).append(", "); sb.append("Database=").append(influxDbProperties.getDatabase()).append(", "); sb.append("Username=").append(influxDbProperties.getUsername()).append(", "); sb.append("Password=").append(influxDbProperties.getPassword()).append(", "); sb.append("RetentionPolicy=").append(influxDbProperties.getRetentionPolicy()).append(", "); sb.append("ConnectTimeout=").append(influxDbProperties.getConnectTimeout()).append(", "); sb.append("ReadTimeout=").append(influxDbProperties.getReadTimeout()).append(", "); sb.append("WriteTimeout=").append(influxDbProperties.getWriteTimeout()).append(", "); sb.append("GzipEnabled=").append(influxDbProperties.isGzip()).append("]"); return sb.toString(); } }; }
配置文件的内容示例如下:
spring: influxdb: url: http://localhost:8086 username: admin password: adminPass database: integrationTest retention-policy: autogen connect-timeout: 10 read-timeout: 30 write-timeout: 10 gzip: true
但跑测试的时候直接报错了,关键报错信息是:
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'spring.influxdb-org.springframework.data.influxdb.InfluxDBProperties': Could not bind properties to InfluxDBProperties (prefix=spring.influxdb, ignoreInvalidFields=false, ignoreUnknownFields=true, ignoreNestedProperties=false); nested exception is org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 4 errors
Field error in object 'spring.influxdb' on field 'username': rejected value [null]; codes [NotEmpty.spring.influxdb.username,NotEmpty.username,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.influxdb.username,username]; arguments []; default message [username]]; default message [may not be empty]
Field error in object 'spring.influxdb' on field 'url': rejected value [null]; codes [NotEmpty.spring.influxdb.url,NotEmpty.url,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.influxdb.url,url]; arguments []; default message [url]]; default message [may not be empty]
Field error in object 'spring.influxdb' on field 'database': rejected value [null]; codes [NotEmpty.spring.influxdb.database,NotEmpty.database,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.influxdb.database,database]; arguments []; default message [database]]; default message [may not be empty]
Field error in object 'spring.influxdb' on field 'retentionPolicy': rejected value [null]; codes [NotEmpty.spring.influxdb.retentionPolicy,NotEmpty.retentionPolicy,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [spring.influxdb.retentionPolicy,retentionPolicy]; arguments []; default message [retentionPolicy]]; default message [may not be empty]
解决方案
问题根源在于测试类没有触发Spring Boot完整的配置加载流程,也没激活对应的配置环境,你可以通过以下几种方式修复:
1. 添加@SpringBootTest注解(最推荐)
@EnableConfigurationProperties本身不会启动Spring Boot的上下文初始化流程,加上@SpringBootTest后,Spring会完整加载环境配置,自动读取对应环境的配置文件:
@RunWith(SpringRunner.class) @SpringBootTest @EnableConfigurationProperties(InfluxDBProperties.class) public class StupidRepoIntegrationTest { // 原有代码保持不变 }
2. 指定激活的配置环境(如果要加载application-integrationTest.yml)
如果你的目标是加载application-integrationTest.yml,可以用@ActiveProfiles指定对应的环境标识:
@RunWith(SpringRunner.class) @SpringBootTest @ActiveProfiles("integrationTest") @EnableConfigurationProperties(InfluxDBProperties.class) public class StupidRepoIntegrationTest { // 原有代码保持不变 }
3. 轻量化方案:用@TestPropertySource直接指定配置文件
如果不想用@SpringBootTest(比如想做更轻量化的测试),可以直接指定配置文件路径:
@RunWith(SpringRunner.class) @EnableConfigurationProperties(InfluxDBProperties.class) @TestPropertySource(locations = "classpath:application-integrationTest.yml") public class StupidRepoIntegrationTest { // 原有代码保持不变 }
额外检查点
- 确认你的
InfluxDBProperties类上正确标注了@ConfigurationProperties(prefix = "spring.influxdb"),这样Spring才能把配置文件里的前缀和类绑定起来:
@ConfigurationProperties(prefix = "spring.influxdb") public class InfluxDBProperties { // 对应的属性字段、getter/setter,以及@NotEmpty这类校验注解 }
- 确保配置文件放在
src/test/resources目录下,测试时Spring才能正确读取到。
内容的提问来源于stack exchange,提问作者ioreskovic

