问题修复
用 ApplicationContextRunner…
在不启动完整 Spring 上下文的情况下,快速验证 @ConfigurationProperties 的属性绑定、校验约束、默认值、类型转换和 profile 配置。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
用 ApplicationContext通用
解决思路
- 添加测试依赖:spring-boot-starter-test、assertj-core(test scope),以及 spring-boot-configuration-processor(provided scope)
- 使用 ApplicationContextRunner 测试属性绑定,避免启动完整 Spring 上下文
- 确保 @ConfigurationProperties(prefix = "...") 的前缀与测试属性路径一致
- 测试所有属性路径,包括嵌套结构和集合
- 测试校验约束:用 context.hasFailed() 验证 @Validated 类会拒绝非法值
- 测试类型转换:验证 Duration(如 30s)、DataSize(如 50MB)、集合和 Map 能正确转换
- 测试默认值:验证未在测试属性中指定时属性具有正确的默认值
- 测试 profile 特定配置:结合 @Profile 与 ApplicationContextRunner 测试不同环境的配置
- 测试边界情况:包括空字符串、null 值、类型不匹配和越界值
- 排查属性不绑定:检查前缀是否匹配(kebab-case 到 camelCase 的转换)
- 排查校验不触发:确认配置类上存在 @Validated 注解
- 排查上下文启动失败:检查依赖和 @ConfigurationProperties 类结构
- 用 withPropertyValues 传入属性,用 withBean 注册配置类,在 run(context -> {...}) 中断言
- 校验失败时用 assertThat(context).hasFailed().getFailure().hasMessageContaining(...) 断言错误信息
- 校验通过时用 assertThat(context).hasNotFailed() 并断言 bean 属性值
- 测试 Duration 转换:传入 app.features.cacheExpiry=30s,断言等于 Duration.ofSeconds(30)
- 测试逗号分隔列表:传入 app.features.enabledFeatures=feature1,feature2,断言 containsExactly("feature1", "feature2")
- 测试 profile 时在 withPropertyValues() 中使用 spring.profiles.active=profileName
适用边界 · 注意事项
- 需要验证完整 Spring 上下文集成行为(如 bean 间协作、AOP 代理)时,应使用 @SpringBootTest 而非 ApplicationContextRunner
- 需要测试真实外部配置源(如远程配置中心、真实 YAML 文件加载)时,本模式不适用