Spring Boot: настройка настраиваемых свойств и тесты

Я использую Spring Boot 2.0 со стандартным файлом свойств application.yml. Я хотел бы разделить его на отдельные файлы свойств, потому что он становится огромным. Также я хотел бы написать тесты для проверки правильности свойств: значений, которые будут представлены в контексте производственного приложения (а не в тестовом).

Вот мой файл с недвижимостью: SRC / основные / ресурсы / конфигурация / 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

Вы пытались использовать аннотацию @TestPropertySource для определения местоположения ваших файлов конфигурации?

Prashant 04.06.2018 18:16

Кроме того, такие случаи легче отлаживать, если вы можете создать очень простое минимальное приложение и предоставить ссылку на него с github.

Prashant 04.06.2018 18:17

Возможный дубликат Spring @PropertySource с использованием YAML

Shubhendu Pramanik 04.06.2018 18:30

@Prashant вот: github.com/bullet-tooth/spring-custom-properties

Bullet-tooth 04.06.2018 18:42
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
4
4 765
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

@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.

vmaldosan 12.02.2019 16:00

Если это ваш точный код, это означает, что вы читаете свое свойство из неправильного файла свойств.

замените свой ресурс собственности на эту строку.

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

Спасибо за Ваш ответ. Извините, я пропустил это и исправил в своем вопросе. Но это не помогает :(.

Bullet-tooth 04.06.2018 18:37
Ответ принят как подходящий

В общем, я нашел правильный способ иметь собственные свойства yaml в моем приложении.

Проблема в том, что Spring не поддерживает файлы yaml как @PropertySource (ссылка на выпуск). И вот обходной путь, как бороться с тем, что описано в весенняя документация.
Итак, чтобы иметь возможность загружать свойства из файлов yaml, вам необходимо:
* Для реализации EnvironmentPostProcessor
* Прописать в spring.factories

Пожалуйста, посетите этот репозиторий github для полного примера.

Также большое спасибо за вашу поддержку, ребята!

Я немного опоздал на вечеринку, но это тоже может помочь. Решение, представленное в качестве ответа, пока что является лучшим подходом, но вот альтернатива, которую я использовал

Используйте профили и измените bean-компонент PropertySoucesPlaceHolderConfiguration, чтобы загружать необходимые файлы свойств на основе профилей. Он загружает 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;
    }


}

Помните, что сеттеры важны, потому что ConfigurationProperties загружает значения в свойства класса только тогда, когда определены геттеры и сеттеры.

Теперь мы можем автоматически подключать зависимость везде, где это необходимо, и использовать свойство.

Другие вопросы по теме