Spring Boot:自定义属性配置和测试

时间:2018-06-04 16:10:13

标签: java spring spring-boot spring-boot-test

我正在使用带有默认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

4 个答案:

答案 0 :(得分:3)

很明显,我找到了在我的应用中使用自定义yaml属性的正确方法。

问题是Spring不支持yaml文件为@PropertySourcelink to issue)。以下是如何处理spring documentation中描述的解决方法 因此,为了能够从您需要的yaml文件加载属性:
*实施EnvironmentPostProcessor
*在spring.factories

中注册

请访问此github repo以获取完整示例。

另外,非常感谢您的支持,伙计们!

答案 1 :(得分: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());
}
}

希望它有所帮助。

答案 2 :(得分:1)

我参加聚会有点晚了,但这也可能有所帮助。到目前为止,作为答案提供的解决方案是最好的方法,但这是我使用的替代方法

使用配置文件并修改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;
    }

然后创建另一个基于前缀-“ security.oauth2.client”读取属性的bean

@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;
    }


}

记住设置器很重要,因为ConfigurationProperties仅在定义了getter和setter时才将值加载到类的属性中

现在,我们可以在需要的地方自动关联依赖项并使用该属性。

答案 3 :(得分:0)

如果这是您的确切代码,则意味着您正在从错误的属性文件中读取您的属性。

将您的媒体资源替换为此行。

@PropertySource("classpath:config/services.yml")