Using Property Configuration Holders with Plain Spring TestContext Framework: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
No edit summary
 
(8 intermediate revisions by the same user not shown)
Line 2: Line 2:


* [[Spring_Framework_Testing_Concepts#Using_Property_Configuration_Holders_with_Plain_Spring_TestContext_Framework|Spring Framework Testing Concepts]]
* [[Spring_Framework_Testing_Concepts#Using_Property_Configuration_Holders_with_Plain_Spring_TestContext_Framework|Spring Framework Testing Concepts]]
* [[Spring_Boot_Property_Injection#Using_Property_Configuration_Holders_with_Plain_Spring_TestContext_Framework|Spring Boot Property Injection]]


=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|?}}
{{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 {
  ...
}

Playground Example

https://github.com/ovidiuf/playground/tree/master/spring/testing/02-integration-test-with-config-property-holder