Spring Boot:自定义属性配置和测试
Posted
技术标签:
【中文标题】Spring Boot:自定义属性配置和测试【英文标题】:Spring Boot: custom properties configuration and tests 【发布时间】:2018-11-14 00:49:27 【问题描述】:我正在使用带有默认 application.yml
属性文件的 Spring Boot 2.0。我想将它拆分为单独的属性文件,因为它变得很大。
另外我想编写测试来检查属性的正确性:将出现在生产应用程序上下文(而不是测试上下文)中的值。
这是我的属性文件:src/main/resources/config/custom.yml
my-property:
value: 'test'
属性类:
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Data
@Configuration
@ConfigurationProperties(prefix = "my-property")
@PropertySource("classpath:config/custom.yml")
public class MyProperty
private String value;
测试:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyProperty.class)
@EnableConfigurationProperties
public class MyPropertyTest
@Autowired
private MyProperty property;
@Test
public void test()
assertEquals("test", property.getValue());
但测试失败并出现错误:
java.lang.AssertionError:
Expected :test
Actual :null
我还看到,在运行应用程序时,属性值为null
,通过在ApplicationRunner
中打印它。
当我对所有属性使用application.yml
时,它使用相同的配置很好。
如何正确配置属性和测试以使其正常工作? 链接到Github repo
【问题讨论】:
您是否尝试过使用@TestPropertySource
注释来提供配置文件的位置?
如果您可以创建一个非常简单的最小应用程序并从 github 提供指向它的链接,那么这样的情况会更容易调试
Spring @PropertySource using YAML的可能重复
@Prashant 这里是:github.com/bullet-tooth/spring-custom-properties
【参考方案1】:
我找到了在我的应用程序中拥有自定义 yaml 属性的正确方法。
问题是 Spring 不支持 yaml 文件作为 @PropertySource
(link to issue)。这是一个解决方法,如何处理spring documentation 中描述的问题。
因此,为了能够从您需要的 yaml 文件中加载属性:
* 实现EnvironmentPostProcessor
* 注册到spring.factories
请访问github repo 获取完整示例。
另外,非常感谢你们的支持,伙计们!
【讨论】:
【参考方案2】:@TestPropertySource
可以解决你的问题。
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyProperty.class)
@TestPropertySource(locations="classpath:test.properties")
public class MyPropertyTest
@Autowired
private MyProperty property;
@Test
public void test()
assertEquals("test", property.getValue());
希望对你有帮助。
【讨论】:
正如 OP 在接受的答案中提到的,@TestPropertySource
目前不适用于 yml 文件。【参考方案3】:
我参加聚会有点晚了,但这也可能有所帮助。作为答案提供的解决方案是迄今为止最好的方法,但这是我使用的替代方法
利用配置文件并修改 PropertySoucesPlaceHolderConfiguration bean 以根据配置文件加载必要的属性文件。它将 application.properties 作为默认值加载,但其他属性文件 -oauth_DEV 和 oauth_QA 是根据配置文件集加载的
@Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurerconfigurer()
System.out.println("Inside Placeholder bean");
PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer();
ClassPathResource cls1= new ClassPathResource("application.properties");
ClassPathResource cls2 = null;
Map<String, Object> propMap = ((ConfigurableEnvironment) ctx.getEnvironment()).getSystemProperties();
for(Map.Entry<String, Object> entrySet: propMap.entrySet())
System.out.println("Map.Key:"+entrySet.getKey()+" Map.valiue:"+entrySet.getValue());
List<String> profiles= Arrays.asList(ctx.getEnvironment().getActiveProfiles());
if(profiles == null || profiles.isEmpty())
if(!propMap.containsKey("spring.profiles.active"))
cls2 = new ClassPathResource("oauth-default.properties");
else
cls2 = new ClassPathResource("oauth-"+propMap.get("spring.profiles.active")+".properties");
else
for(String profile:profiles)
if(profile.equalsIgnoreCase("DEV"))
cls2 = new ClassPathResource("oauth-DEV.properties");
else if(profile.equalsIgnoreCase("QA"))
cls2 = new ClassPathResource("oauth-QA.properties");
else if (profile.equalsIgnoreCase("UAT"))
cls2 = new ClassPathResource("oauth-UAT.properties");
else if(profile.equalsIgnoreCase("PROD"))
cls2 = new ClassPathResource("oauth-PROD.properties");
else
cls2 = new ClassPathResource("oauth-default.properties");
cfg.setLocations(cls1,cls2);
//cfg.setPlaceholderPrefix("#");
return cfg;
然后创建另一个读取基于前缀的属性的bean - “security.oauth2.client”
@Configuration
@ConfigurationProperties(prefix="security.oauth2.client")
public class OauthSecurityConfigurationDto
private String clientId;
private String clientSecret;
private String scope;
private String accessTokenUri;
private String userAuthorizationUri;
private String grantType;
private String resourceIds;
private String registeredRedirectUri;
private String preEstablishedRedirectUri;
private String useCurrentUri;
private String userInfoUri;
public String getClientId()
return clientId;
public void setClientId(String clientId)
this.clientId = clientId;
public String getClientSecret()
return clientSecret;
public void setClientSecret(String clientSecret)
this.clientSecret = clientSecret;
public String getScope()
return scope;
public void setScope(String scope)
this.scope = scope;
public String getAccessTokenUri()
return accessTokenUri;
public void setAccessTokenUri(String accessTokenUri)
this.accessTokenUri = accessTokenUri;
public String getUserAuthorizationUri()
return userAuthorizationUri;
public void setUserAuthorizationUri(String userAuthorizationUri)
this.userAuthorizationUri = userAuthorizationUri;
public String getGrantType()
return grantType;
public void setGrantType(String grantType)
this.grantType = grantType;
public String getResourceIds()
return resourceIds;
public void setResourceIds(String resourceIds)
this.resourceIds = resourceIds;
public String getRegisteredRedirectUri()
return registeredRedirectUri;
public void setRegisteredRedirectUri(String registeredRedirectUri)
this.registeredRedirectUri = registeredRedirectUri;
public String getPreEstablishedRedirectUri()
return preEstablishedRedirectUri;
public void setPreEstablishedRedirectUri(String preEstablishedRedirectUri)
this.preEstablishedRedirectUri = preEstablishedRedirectUri;
public String getUseCurrentUri()
return useCurrentUri;
public void setUseCurrentUri(String useCurrentUri)
this.useCurrentUri = useCurrentUri;
public String getUserInfoUri()
return userInfoUri;
public void setUserInfoUri(String userInfoUri)
this.userInfoUri = userInfoUri;
记住 setter 很重要,因为 ConfigurationProperties
只有在定义了 getter 和 setter 时才会将值加载到类的属性中
现在我们可以在需要的地方自动装配依赖项并使用该属性。
【讨论】:
【参考方案4】:如果这是您的确切代码,则意味着您正在从错误的属性文件中读取您的属性。
将您的属性资源替换为这一行。
@PropertySource("classpath:config/services.yml")
【讨论】:
感谢您的回答。对不起,我错过了,并修正了我的问题。但这无济于事:(。 docs.spring.io/spring-boot/docs/1.2.0.RELEASE/reference/…以上是关于Spring Boot:自定义属性配置和测试的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot? 配置文件详解:自定义属性随机数多环境配置等
Spring boot 的 properties 属性值配置 application.properties 与 自定义properties