如何在不使用@SpringBootTest的情况下测试Spring Boot配置类?
解决Spring Boot 2.7.x Kotlin配置类轻量测试的属性绑定问题
问题场景
使用Kotlin与Spring Boot 2.7.18,希望不依赖@SpringBootTest注解测试配置类,但测试运行时无法从application-test.yml绑定配置属性到TestAESProperty类,报错信息如下:
Failed to bind properties under 'common.test.aes' to TestAESProperty Parameter specified as non-null is null: method TestAESProperty.<init>, parameter key Error creating bean with name 'TestAESProperty' Could not bind properties to 'TestAESProperty' : prefix=common.test.aes, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'common.test.aes' to TestAESProperty
现有代码结构:
测试类
@ActiveProfiles("test") @ExtendWith(SpringExtension::class) @ContextConfiguration(classes = [TestConfig::class]) class AESTest { @Autowired lateinit var properties: TestAESProperty @Test fun decrypt() { assertEquals(properties.key, "hello") assertEquals(properties.iv, "world") } }
配置类
@TestConfiguration @EnableConfigurationProperties(TestAESProperty::class) class TestConfig { }
配置属性类
@ConstructorBinding @ConfigurationProperties(prefix = "common.test.aes") data class TestAESProperty( val key: String, val iv: String, )
application-test.yml配置
spring: config: activate: on-profile: test common: test: aes: key: hello iv: world
问题原因
仅通过@ExtendWith(SpringExtension::class)+@ContextConfiguration搭建的轻量测试上下文,未加载Spring Boot完整的配置属性绑定机制,尤其是@ConstructorBinding依赖的处理器,同时也未正确触发测试配置文件的加载逻辑。
解决方案
方法一:保留构造绑定,引入配置属性自动配置类
修改测试类,显式引入Spring Boot的ConfigurationPropertiesAutoConfiguration以激活完整属性绑定流程,并指定测试配置文件路径:
@ActiveProfiles("test") @ExtendWith(SpringExtension::class) @ContextConfiguration( classes = [ TestConfig::class, ConfigurationPropertiesAutoConfiguration::class // 引入配置属性自动配置类 ] ) @TestPropertySource(locations = ["classpath:application-test.yml"]) // 显式加载测试配置文件 class AESTest { @Autowired lateinit var properties: TestAESProperty @Test fun decrypt() { assertEquals(properties.key, "hello") assertEquals(properties.iv, "world") } }
方法二:替换构造绑定为字段绑定
如果无需不可变属性的构造注入特性,可以去掉@ConstructorBinding,将属性改为可变类型并设置默认值:
@ConfigurationProperties(prefix = "common.test.aes") data class TestAESProperty( var key: String = "", var iv: String = "" )
测试类无需额外修改,保留原有配置即可运行。
方案说明
- 方法一保留了
@ConstructorBinding的不可变属性特性,适合对数据不可变性有要求的场景,同时完整复用Spring Boot的属性绑定逻辑。 - 方法二实现更简单,适合对属性可变性无严格要求的场景,避免了构造绑定在轻量测试中的兼容性问题。
内容的提问来源于stack exchange,提问作者Crispy
相关产品推荐
相关产品推荐

