Using Property Configuration Holders with Plain Spring TestContext Framework: Difference between revisions
Jump to navigation
Jump to search
(6 intermediate revisions by the same user not shown) | |||
Line 6: | Line 6: | ||
=Overview= | =Overview= | ||
Property configuration holders are a Spring Boot pattern. They require Spring Boot dependencies and runtime to function. However, they're useful, so this is a method to get them to work with plain TestContext Framework tests. | Property configuration holders are a Spring Boot pattern. They require Spring Boot dependencies and runtime to function. However, they're useful, so this is a method to get them to work with plain TestContext Framework tests. | ||
=Procedure= | |||
To configure tests to load configuration properties from ./src/test/resources/application.yml: | |||
1. Add the following dependencies: | |||
<syntaxhighlight lang='groovy'> | |||
implementation('org.springframework.boot:spring-boot') | |||
testImplementation('org.yaml:snakeyaml:1.23') | |||
</syntaxhighlight> | |||
2. <span id='Custom_Initializer'></span>Configure the test with a custom initializer. | |||
<syntaxhighlight lang='java'> | |||
@RunWith(SpringRunner.class) | |||
@ContextConfiguration( | |||
classes = {...}, | |||
initializers = PropertyAwareTestContextInitializer.class) | |||
public class ExampleTests { | |||
... | |||
} | |||
</syntaxhighlight> | |||
3. This is the custom initializer. | |||
<syntaxhighlight lang='java'> | |||
... | |||
import org.springframework.boot.SpringApplication; | |||
import org.springframework.boot.context.config.ConfigFileApplicationListener; | |||
import org.springframework.context.ApplicationContextInitializer; | |||
import org.springframework.context.ConfigurableApplicationContext; | |||
public class PropertyAwareTestContextInitializer | |||
implements ApplicationContextInitializer<ConfigurableApplicationContext> { | |||
@Override | |||
public void initialize(ConfigurableApplicationContext applicationContext) { | |||
// | |||
// expose ./src/test/resources/application.yml as a property source | |||
// | |||
new ConfigFileApplicationListener().postProcessEnvironment( | |||
applicationContext.getEnvironment(), new SpringApplication()); | |||
// | |||
// register a BeanPostProcessor that loads the property values from the environment into | |||
// @ConfigurationProperties classes | |||
// | |||
applicationContext.addBeanFactoryPostProcessor( | |||
beanFactory -> beanFactory.addBeanPostProcessor( | |||
applicationContext.getBean(PropertyAwareTestContextConfiguration.class). | |||
getConfigurationPropertiesBindingPostProcessor())); | |||
} | |||
} | |||
</syntaxhighlight> | |||
4. Provide additional required beans in the form of a @Configuration: | |||
<syntaxhighlight lang='java'> | |||
... | |||
import org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata; | |||
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor; | |||
import org.springframework.context.annotation.Bean; | |||
import org.springframework.context.annotation.Configuration; | |||
@Configuration | |||
public class PropertyAwareTestContextConfiguration { | |||
@Bean | |||
public ConfigurationPropertiesBindingPostProcessor getConfigurationPropertiesBindingPostProcessor() { | |||
return new ConfigurationPropertiesBindingPostProcessor(); | |||
} | |||
@Bean("org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata") | |||
public ConfigurationBeanFactoryMetadata getConfigurationBeanFactoryMetadata() { | |||
return new ConfigurationBeanFactoryMetadata(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
5. List the @Configuration among those the test is configured with: | |||
<syntaxhighlight lang='java'> | |||
@RunWith(SpringRunner.class) | |||
@ContextConfiguration( | |||
classes = { | |||
..., | |||
PropertyAwareTestContextConfiguration.class}, | |||
initializers = PropertyAwareContextInitializer.class) | |||
public class ExampleTests { | |||
... | |||
} | |||
</syntaxhighlight> | |||
=Playground Example= | =Playground Example= | ||
{{External|https://github.com/ovidiuf/playground/tree/master/spring/testing/02-integration-test-with-config-property-holder}} | {{External|https://github.com/ovidiuf/playground/tree/master/spring/testing/02-integration-test-with-config-property-holder}} |
Latest revision as of 06:46, 6 December 2018
Internal
Overview
Property configuration holders are a Spring Boot pattern. They require Spring Boot dependencies and runtime to function. However, they're useful, so this is a method to get them to work with plain TestContext Framework tests.
Procedure
To configure tests to load configuration properties from ./src/test/resources/application.yml:
1. Add the following dependencies:
implementation('org.springframework.boot:spring-boot')
testImplementation('org.yaml:snakeyaml:1.23')
2. Configure the test with a custom initializer.
@RunWith(SpringRunner.class)
@ContextConfiguration(
classes = {...},
initializers = PropertyAwareTestContextInitializer.class)
public class ExampleTests {
...
}
3. This is the custom initializer.
...
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
public class PropertyAwareTestContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//
// expose ./src/test/resources/application.yml as a property source
//
new ConfigFileApplicationListener().postProcessEnvironment(
applicationContext.getEnvironment(), new SpringApplication());
//
// register a BeanPostProcessor that loads the property values from the environment into
// @ConfigurationProperties classes
//
applicationContext.addBeanFactoryPostProcessor(
beanFactory -> beanFactory.addBeanPostProcessor(
applicationContext.getBean(PropertyAwareTestContextConfiguration.class).
getConfigurationPropertiesBindingPostProcessor()));
}
}
4. Provide additional required beans in the form of a @Configuration:
...
import org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class PropertyAwareTestContextConfiguration {
@Bean
public ConfigurationPropertiesBindingPostProcessor getConfigurationPropertiesBindingPostProcessor() {
return new ConfigurationPropertiesBindingPostProcessor();
}
@Bean("org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata")
public ConfigurationBeanFactoryMetadata getConfigurationBeanFactoryMetadata() {
return new ConfigurationBeanFactoryMetadata();
}
}
5. List the @Configuration among those the test is configured with:
@RunWith(SpringRunner.class)
@ContextConfiguration(
classes = {
...,
PropertyAwareTestContextConfiguration.class},
initializers = PropertyAwareContextInitializer.class)
public class ExampleTests {
...
}