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

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
(Created page with "=Internal= * Spring Framework Testing Concepts =Playground...")
 
 
(9 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=
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