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

     2023-02-26     178

关键词:

【中文标题】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/…

使用自定义 ErrorAttributes 测试 Spring Boot 应用程序?

】使用自定义ErrorAttributes测试SpringBoot应用程序?【英文标题】:TestingaSpringBootapplicationwithcustomErrorAttributes?【发布时间】:2015-05-2104:07:23【问题描述】:我正在尝试测试应使用自定义错误属性的SpringBootRestController。@BeanpublicErrorAtt... 查看详情

使用自定义 ErrorAttributes 测试 Spring Boot 应用程序?

】使用自定义ErrorAttributes测试SpringBoot应用程序?【英文标题】:TestingaSpringBootapplicationwithcustomErrorAttributes?【发布时间】:2015-05-2104:07:23【问题描述】:我正在尝试测试应使用自定义错误属性的SpringBootRestController。@BeanpublicErrorAtt... 查看详情

自定义 Spring Boot 启动器不应用属性

】自定义SpringBoot启动器不应用属性【英文标题】:CustomSpringbootstarterdonotapplyproperty【发布时间】:2018-12-2414:19:13【问题描述】:创建自定义SpringBoot启动器我的弹簧启动启动器从spring-boot-starter-parent.在我的Starter的源文件夹中添加... 查看详情

Spring Boot - 使用自定义 PreAuthorize 表达式和身份验证测试 Rest Api

】SpringBoot-使用自定义PreAuthorize表达式和身份验证测试RestApi【英文标题】:SpringBoot-TestRestApiWithCustomPreAuthorizeExpressionandAuthentication【发布时间】:2018-10-0710:53:00【问题描述】:我正在寻找一种如何使用以下设置测试SpringBootRESTAPI... 查看详情

在 Jackson / Spring Boot 中测试自定义 Json Deserializer

】在Jackson/SpringBoot中测试自定义JsonDeserializer【英文标题】:TestingcustomJsonDeserializerinJackson/SpringBoot【发布时间】:2020-05-2012:02:56【问题描述】:我正在尝试将单元测试写入自定义反序列化程序,该反序列化程序使用带有@Autowired参... 查看详情

测试开发专题:spring-boot自定义返回参数校验错误信息

之前两篇文章Spring-boot自定义参数校验注解和如何在spring-boot中进行参数校验,我们介绍了,参数校验以及如何自定义参数校验注解,但是当传递参数出错时,只是把错误信息打印到了控制台,合理的做法是应该把校验的错误信... 查看详情

测试开发专题:spring-boot自定义返回参数校验错误信息

之前两篇文章Spring-boot自定义参数校验注解和如何在spring-boot中进行参数校验,我们介绍了,参数校验以及如何自定义参数校验注解,但是当传递参数出错时,只是把错误信息打印到了控制台,合理的做法是应该把校验的错误信... 查看详情

企业级spring-boot案例-自定义springbootstarter(代码片段)

文章目录1.未使用SpringBootStarter前的情况2.SpringBootStarter简介2.1什么是SpringBootStarter(启动器)2.2Starter模块整体结构2.3Spring官方提供的Starter和Starter命名规范3.自定义SpringBootStarter3.1根据starter命名规范创建一个springboot项目3.2... 查看详情

Spring Boot 测试自定义错误控制器

】SpringBoot测试自定义错误控制器【英文标题】:SpringBoottestcustomErrorsController【发布时间】:2017-12-0318:43:15【问题描述】:按照此处SpringBootRemoveWhitelabelErrorPage的建议,我创建了一个自定义错误控制器,以json格式返回自定义错误... 查看详情

为啥使用 webflux 进行 spring boot 测试会忽略自定义 jackson 模块

】为啥使用webflux进行springboot测试会忽略自定义jackson模块【英文标题】:Whydoesspringboottestwithwebfluxignorecustomjacksonmodule为什么使用webflux进行springboot测试会忽略自定义jackson模块【发布时间】:2018-10-2001:54:40【问题描述】:我正在使... 查看详情

在 Spring Boot MVC 测试中自定义 bean

】在SpringBootMVC测试中自定义bean【英文标题】:customizebeansinspringbootMVCtest【发布时间】:2017-06-2101:34:51【问题描述】:我正在使用Spring-boot1.4.0.RELEASE。已按照建议构建了一个MVCint测试https://docs.spring.io/spring-boot/docs/current/reference/htm... 查看详情

如何在 Spring Boot Rest api 响应的 ResponseEntity 中添加自定义属性

】如何在SpringBootRestapi响应的ResponseEntity中添加自定义属性【英文标题】:HowtoaddcustomattributesinResponseEntityofSpringBootRestapiresponse【发布时间】:2020-05-0916:57:53【问题描述】:由于springboot提供了ResponseEntity来表示对restapi的HTTP响应,... 查看详情

Spring 安全性和自定义 AuthenticationFilter 与 Spring boot

】Spring安全性和自定义AuthenticationFilter与Springboot【英文标题】:SpringsecurityandcustomAuthenticationFilterwithSpringboot【发布时间】:2014-10-2311:08:59【问题描述】:我有自定义身份验证过滤器,它创建PreAuthenticatedAuthenticationToken并将其存储... 查看详情

如何在 Spring Boot 和 JUnit 测试中定义 spring.config.location?

】如何在SpringBoot和JUnit测试中定义spring.config.location?【英文标题】:Howtodefinethespring.config.locationonSpringBootandJUnittests?【发布时间】:2019-02-0801:16:17【问题描述】:在运行JUnit测试时,我们如何以编程方式配置SpringBoot以定义spring.co... 查看详情

使用 IntelliJ 在 Spring Boot 中自定义应用程序属性

】使用IntelliJ在SpringBoot中自定义应用程序属性【英文标题】:CustomapplicationpropertiesinspringbootusingIntelliJ【发布时间】:2020-04-3005:00:37【问题描述】:我正在尝试使用application.properties以外的应用程序属性,例如资源目录中的applicatio... 查看详情

在 Spring Boot 中编写自定义查询

】在SpringBoot中编写自定义查询【英文标题】:writingcustomqueriesinSpringboot【发布时间】:2016-03-2202:11:31【问题描述】:我最近开始使用Springboot,但遇到了一些问题。以前,当我只是将Spring数据与hibernate和JPA一起使用时,我可以创... 查看详情

在 Spring Boot 中的异常处理期间保留自定义 MDC 属性

】在SpringBoot中的异常处理期间保留自定义MDC属性【英文标题】:PreservecustomMDCattributesduringexception-handlinginSpringBoot【发布时间】:2019-08-0410:12:01【问题描述】:短版(有足够的细节)如何保留在javax.servlet.Filter实现的doFilter()方法... 查看详情

Spring Boot 自动配置覆盖自定义(elasticsearchTemplate)配置

】SpringBoot自动配置覆盖自定义(elasticsearchTemplate)配置【英文标题】:Springbootautoconfigurationoverridingcustom(elasticsearchTemplate)configuration【发布时间】:2018-08-1309:14:12【问题描述】:我创建了以下配置(我复制了@Lazy,因为我无法使... 查看详情