package com.nanri.aiimage.config; import org.junit.jupiter.api.Test; import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.ClassPathResource; import java.io.IOException; import java.util.Collections; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; /** * application.yml 默认值与 env 覆盖测试(任务 53)。 * 用 Spring 的 YamlPropertySourceLoader 真实解析 application.yml, * 再经 StandardEnvironment 验证 ${VAR:default} 占位符的默认值与 env 覆盖语义。 */ class RequestTraceConfigTest { private static final String KEY = "aiimage.instance-routing.request-body-cache-limit-bytes"; private static String rawYmlValue() throws IOException { YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); List> sources = loader.load("app.yml", new ClassPathResource("application.yml")); for (PropertySource source : sources) { Object value = source.getProperty(KEY); if (value != null) { return String.valueOf(value); } } throw new AssertionError("application.yml 未包含 " + KEY); } private static String resolve(String raw, String envValue) { StandardEnvironment environment = new StandardEnvironment(); environment.getPropertySources().addFirst(new MapPropertySource( "test-env", envValue == null ? Collections.emptyMap() : Collections.singletonMap("AIIMAGE_INSTANCE_ROUTE_REQUEST_BODY_CACHE_LIMIT_BYTES", envValue))); return environment.resolvePlaceholders(raw); } @Test void ymlDefaultIs1MiB() throws IOException { assertTrue(rawYmlValue().contains("1048576"), "yml 默认值 1048576(1MB)"); } @Test void envOverrideTakesEffect() throws IOException { assertEquals("2097152", resolve(rawYmlValue(), "2097152"), "env 覆盖生效"); } @Test void envOverrideLarge() throws IOException { assertEquals("104857600", resolve(rawYmlValue(), "104857600"), "大值覆盖生效"); } @Test void envOverrideSmallIsKeptThenClampedByCode() throws IOException { // env 注入 1024(<1MB):yml 层原样解析,钳制在代码层 Math.max(1024*1024, …) assertEquals("1024", resolve(rawYmlValue(), "1024")); } @Test void placeholderFormat() throws IOException { assertTrue(rawYmlValue().matches("\\$\\{AIIMAGE_INSTANCE_ROUTE_REQUEST_BODY_CACHE_LIMIT_BYTES:1048576}"), "占位符格式 ${VAR:default}"); } @Test void defaultMatchesCodeConstant() throws IOException { assertEquals("1048576", resolve(rawYmlValue(), null), "未设 env 时解析为 1048576,与代码 @Value 默认一致"); } @Test void envUnsetUsesDefault() throws IOException { assertFalse(resolve(rawYmlValue(), null).startsWith("${"), "未设 env 时占位符被解析为默认值而非保留原文"); assertEquals("1048576", resolve(rawYmlValue(), null)); } @Test void ymlLoadsUnderSpringEnv() throws IOException { YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); List> sources = loader.load("app.yml", new ClassPathResource("application.yml")); assertFalse(sources.isEmpty(), "application.yml 能被 YamlPropertySourceLoader 加载"); boolean found = false; for (PropertySource source : sources) { if (source.containsProperty(KEY)) { found = true; } } assertTrue(found, "instance-routing.request-body-cache-limit-bytes 存在于 yml 配置源"); } }