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

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(5 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. To configure tests to load configuration properties from ./src/test/resources/application.yml:
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:
1. Add the following dependencies:
Line 15: Line 19:
</syntaxhighlight>
</syntaxhighlight>


2. Configure the test with a custom initializer:
2. <span id='Custom_Initializer'></span>Configure the test with a custom initializer.


<syntaxhighlight lang='java'>
<syntaxhighlight lang='java'>
Line 21: Line 25:
@ContextConfiguration(
@ContextConfiguration(
   classes = {...},
   classes = {...},
   initializers = PropertyAwareContextInitializer.class)
   initializers = PropertyAwareTestContextInitializer.class)
public class ExampleTests {
public class ExampleTests {
   ...
   ...
Line 27: Line 31:
</syntaxhighlight>
</syntaxhighlight>


3. This is the custom initializer:
3. This is the custom initializer.


<syntaxhighlight lang='java'>
<syntaxhighlight lang='java'>
Line 59: Line 63:
           getConfigurationPropertiesBindingPostProcessor()));
           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>
</syntaxhighlight>

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