2014-01-21 5 views
49

Spring Boot позволяет нам заменять наши файлы application.properties эквивалентами YAML. Однако я, кажется, попал в ловушку с моими испытаниями. Если я аннотирую свой TestConfiguration (простой Java-конфиг), он ожидает файл свойств.Spring @PropertySource с использованием YAML

Например это не работает: @PropertySource(value = "classpath:application-test.yml")

Если у меня есть это в моем YAML файле:

db: 
    url: jdbc:oracle:thin:@pathToMyDb 
    username: someUser 
    password: fakePassword 

И я бы используя эти значения с чем-то вроде этого:

@Value("${db.username}") String username 

Тем не менее, в итоге я получаю ошибку и так:

Could not resolve placeholder 'db.username' in string value "${db.username}" 

Как я могу использовать доброту YAML в своих тестах?

+0

Определить «не работает». Какое исключение/ошибка/предупреждение? –

+0

Spring Boot выравнивает файл YAML, поэтому он отображается как файл свойств с точечной нотацией. Это сглаживание не происходит. – checketts

+0

И просто для подтверждения, это работает в не-тестовом коде? –

ответ

28

весна-Загрузочная помощника для этого, просто добавьте

@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) 

в верхней части тестовых классов или абстрактном тест суперкласса.

+1

Это не работает для меня, свойства не загружены. –

9

Подход к загрузке свойств YAML, ИМХО можно сделать двумя способами:

а. Вы можете поместить конфигурацию в стандартное местоположение - application.yml в корневой путь к классу - обычно src/main/resources, и это свойство yaml должно автоматически загружаться загрузкой Spring с указанным вами именем сглаженного пути.

b. Второй подход немного более обширна, в основном определяют класс, чтобы держать ваши свойства таким образом:

@ConfigurationProperties(path="classpath:/appprops.yml", name="db") 
public class DbProperties { 
    private String url; 
    private String username; 
    private String password; 
... 
} 

Поэтому в основном это говорит, что загрузить файл YAML и заполнить класс DbProperties на основе корневого элемента «дб ».

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

@EnableConfigurationProperties(DbProperties.class) 
public class PropertiesUsingService { 

    @Autowired private DbProperties dbProperties; 

} 

Любой из этих подходов должны работать для вас чисто с использованием Spring-загрузки.

+0

Убедитесь, что у вас есть snakeyml в вашем классе, и выше должно работать. – hoserdude

+3

В эти дни (хотя не в тот момент, когда задавался этот вопрос), 'snakeyaml' втягивается как транзитивная зависимость от' spring-boot-starter', поэтому не нужно добавлять его в свой 'pom.xml' или 'build.gradle', если у вас нет глубокого стремления использовать другую версию. :) – Steve

+1

Это теперь 'местоположения', а не' путь', а также 'ConfigFileApplicationContextInitializer' также требуется. – OrangeDog

19

@PropertySource поддерживает только файлы свойств (это ограничение от Spring, а не самой загрузки). Не стесняйтесь, чтобы открыть билет с запросом на функцию in JIRA.

+0

Я надеялся, что существует способ повторно использовать прослушиватель yaml или вручную загрузить yaml в среде, которая может быть передана в тестовую конфигурацию. – checketts

+10

Я предполагаю, что вы можете написать «ApplicationContextInitializer» и добавить его в тестовую конфигурацию (просто используйте «YamlPropertySourceLoader» для улучшения «Среда»). Лично я бы предпочел, чтобы '@ PropertySource' поддерживал это поведение изначально. –

+0

это все еще так? does '@PropertySource' не поддерживает YAML? – domi

0

это потому, что вы не настроили snakeyml. Весенняя обувь поставляется с функцией @EnableAutoConfiguration. есть snakeyml конфигурации тоже, когда и называют эту аннотацию ..

это мой путь:

@Configuration 
@EnableAutoConfiguration 
public class AppContextTest { 
} 

вот мой тест:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(
     classes = { 
       AppContextTest.class, 
       JaxbConfiguration.class, 
     } 
) 

public class JaxbTest { 
//tests are ommited 
} 
3

Я нашел обходной путь с помощью @ActiveProfiles("test") и добавления файл application-test.yml для src/test/resources.

Кончилось выглядеть так:

@SpringApplicationConfiguration(classes = Application.class, initializers = ConfigFileApplicationContextInitializer.class) 
@ActiveProfiles("test") 
public abstract class AbstractIntegrationTest extends AbstractTransactionalJUnit4SpringContextTests { 

} 

Файл приложения test.yml содержит только те свойства, которые я хочу, чтобы переопределить из application.yml (который можно найти в SRC/основные/ресурсов) ,

+0

Это то, что я пытался использовать. По какой-то причине это не работает (Spring Boot 1.3.3), когда я использую '@Value (" $ {my.property} ")', но он отлично работает, если я использую 'environment.getProperty (« my.property ») '. –

1

мне нужно прочитать некоторые свойства в мой код, и это работает с пружинным ботинке 1.3.0.RELEASE

@Autowired 
private ConfigurableListableBeanFactory beanFactory; 

// access a properties.yml file like properties 
@Bean 
public PropertySource properties() { 
    PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer(); 
    YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean(); 
    yaml.setResources(new ClassPathResource("properties.yml")); 
    propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject()); 
    // properties need to be processed by beanfactory to be accessible after 
    propertySourcesPlaceholderConfigurer.postProcessBeanFactory(beanFactory); 
    return propertySourcesPlaceholderConfigurer.getAppliedPropertySources().get(PropertySourcesPlaceholderConfigurer.LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME); 
} 
1

в тестовом блоке @value имеет некоторые проблемы собственности вызова из файла свойств, так и можно использовать среда заменить значение

@Autowired 
private Environment environment; 
public void init(){ 

    String username=environment.getRequiredProperty("db.username"); 

} 

так что вы будете в состоянии назвать недвижимость в настоящее время в производстве и испытательной установки

25

Как было упомянуто @PropertySource не загружает файл yaml. В качестве обходного решения загрузите файл самостоятельно и добавьте загруженные свойства в Environment.

Implemement ApplicationContextInitializer:

public class YamlFileApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { 
    @Override 
    public void initialize(ConfigurableApplicationContext applicationContext) { 
    try { 
     Resource resource = applicationContext.getResource("classpath:file.yml"); 
     YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader(); 
     PropertySource<?> yamlTestProperties = sourceLoader.load("yamlTestProperties", resource, null); 
     applicationContext.getEnvironment().getPropertySources().addFirst(yamlTestProperties); 
    } catch (IOException e) { 
     throw new RuntimeException(e); 
    } 
    } 
} 

Добавить инициализатору к тесту:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class, initializers = YamlFileApplicationContextInitializer.class) 
public class SimpleTest { 
    @Test 
    public test(){ 
    // test your properties 
    } 
} 
+0

На самом деле это должен быть лучший ответ, спасибо, что он сработал! – Adelin

+0

Это обойти https://jira.spring.io/browse/SPR-13912? – bobmarksie

4

Другой вариант, чтобы установить spring.config.location через @TestPropertySource:

@TestPropertySource(properties = { "spring.config.location = classpath:<path-to-your-yml-file>" } 
7

С весны Ботинок 1.4, вы можете использовать новый @SpringBootTest, чтобы добиться этого проще (и упростить настройку интеграции в целом), загрузив ваши интеграционные тесты, используя поддержку Spring Boot.

Подробная информация на Spring Blog.

Насколько я могу судить, это означает, что вы получаете все преимущества Spring Boot externalized config goodness, как и в вашем производственном коде, включая автоматическое получение конфигурации YAML из пути к классам.

По умолчанию эта аннотация будет

... первая попытка загрузить @Configuration от каких-либо внутренних классов, и если это не удается, он будет искать для вашего основного @SpringBootApplication класса.

, но при необходимости вы можете указать другие классы конфигурации.

В данном конкретном случае, вы можете комбинировать @SpringBootTest с @ActiveProfiles("test") и весной будет забрать свой YAML конфигурацию, при условии, что следует нормальной загрузка именования стандартов (т.е. application-test.yml).

@RunWith(SpringRunner.class) 
@SpringBootTest 
@ActiveProfiles("test") 
public class SpringBootITest { 

    @Value("${db.username}") 
    private String username; 

    @Autowired 
    private MyBean myBean; 

    ... 

} 

Примечание: SpringRunner.class это новое название для SpringJUnit4ClassRunner.class

0

Загрузка пользовательских YML файл с многократным профиля конфигурации в Spring ботинке.

1) Добавить свойство боб с SpringBootApplication начать следующим образом

@SpringBootApplication 
@ComponentScan({"com.example.as.*"}) 
public class TestApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(TestApplication.class, args); 
    } 

    @Bean 
    @Profile("dev") 
    public PropertySourcesPlaceholderConfigurer propertiesStage() { 
     return properties("dev"); 
    } 

    @Bean 
    @Profile("stage") 
    public PropertySourcesPlaceholderConfigurer propertiesDev() { 
     return properties("stage"); 
    } 

    @Bean 
    @Profile("default") 
    public PropertySourcesPlaceholderConfigurer propertiesDefault() { 
     return properties("default"); 

    } 
    /** 
    * Update custom specific yml file with profile configuration. 
    * @param profile 
    * @return 
    */ 
    public static PropertySourcesPlaceholderConfigurer properties(String profile) { 
     PropertySourcesPlaceholderConfigurer propertyConfig = null; 
     YamlPropertiesFactoryBean yaml = null; 

     propertyConfig = new PropertySourcesPlaceholderConfigurer(); 
     yaml = new YamlPropertiesFactoryBean(); 
     yaml.setDocumentMatchers(new SpringProfileDocumentMatcher(profile));// load profile filter. 
     yaml.setResources(new ClassPathResource("env_config/test-service-config.yml")); 
     propertyConfig.setProperties(yaml.getObject()); 
     return propertyConfig; 
    } 
} 

2) Конфигурация объекта POJO Java следующим

@Component 
@JsonIgnoreProperties(ignoreUnknown = true) 
@JsonInclude(Include.NON_NULL) 
@ConfigurationProperties(prefix = "test-service") 
public class TestConfig { 

    @JsonProperty("id") 
    private String id; 

    @JsonProperty("name") 
    private String name; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

3) Создание пользовательского YML (и поместите его под путь ресурса следующим образом: YML Имя файла: test-service-config.yml

Например, Config в файле yml.

test-service: 
    id: default_id 
    name: Default application config 
--- 
spring: 
    profiles: dev 

test-service: 
    id: dev_id 
    name: dev application config 

--- 
spring: 
    profiles: stage 

test-service: 
    id: stage_id 
    name: stage application config 
Смежные вопросы