You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不使用@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 23:18:25