如何在Spring测试中用@TestPropertySource解析属性占位符?
问题根源与解决方案
你的问题出在两个关键误用:
1. @TestPropertySource注解的位置错误
@TestPropertySource是测试类专属注解,只能用在测试类上,不能放在@Configuration配置类中。你之前把它写在配置类里,Spring Test框架根本不会处理这个注解,导致配置的属性完全无法加载到上下文。
2. 手动导入PropertySourcesPlaceholderConfigurer干扰自动配置
Spring Boot已经自动配置了适配测试环境的占位符解析器,手动导入PropertySourcesPlaceholderConfigurer会覆盖这个自动配置的实例。而自定义的解析器初始化时机早于Spring Test加载测试属性源的时机,自然无法读取@TestPropertySource中的配置。
修改后的正确代码
测试类调整
将@TestPropertySource移到测试类上,移除配置类中多余的@Import和@TestPropertySource:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = ServerPropertiesTest.ServerPropertiesTestConfig.class) @TestPropertySource(properties = "server.port=8080") // 移到测试类上 class ServerPropertiesTest { @Autowired GatewayMeta gatewayMeta; @Test void ifNoServerSpecified_serversHasOneServerMatchingLocalhostServerPort() { List<String> servers = gatewayMeta.getServers(); assertThat(servers).hasSize(1); String server = servers.get(0); assertThat(server).isEqualTo("http://localhost:8080"); } @Configuration @EnableConfigurationProperties(GatewayMeta.class) // 移除@Import和@TestPropertySource static class ServerPropertiesTestConfig { } }
属性覆盖场景测试
如果需要用@TestPropertySource覆盖application-test.properties中的配置,只需保持@TestPropertySource在测试类上即可,它的优先级高于@PropertySource,会自动覆盖对应属性:
// 测试类上的配置会覆盖application-test.properties中的server.port @TestPropertySource(properties = "server.port=8000")
更简洁的Spring Boot测试写法
如果是Spring Boot项目,推荐用@SpringBootTest替代手动配置上下文,它会自动加载所有Spring Boot自动配置,代码更简洁:
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(classes = GatewayMeta.class) @TestPropertySource(properties = "server.port=8000") class ServerPropertiesTest { @Autowired GatewayMeta gatewayMeta; @Test void ifNoServerSpecified_serversHasOneServerMatchingLocalhostServerPort() { List<String> servers = gatewayMeta.getServers(); assertThat(servers).containsExactly("http://localhost:8000"); } }
内容的提问来源于stack exchange,提问作者Powet
相关产品推荐
相关产品推荐

