Configuration Properties Not Loading in Spring Boot Test

While trying to test a service layer class which loads properties from a configuration file that reads the information from either an application.yml or a application.properties, I kept running into an issue in which all of the properties were returning null.

My test service class was simple. I figured hmm, maybe loading a properties file is relatively straightforward and a simple injection will do the trick, something like :

@RunWith(SpringRunner.class)
public class SomeServiceTest {
    @Autowired
    private MyConfigProperties configProperties;
}

For reference, my application.yml looks something like this:

myApp:
  someProperty: someKey

And the MyConfigProperties located in our main project:

@ConfigurationProperties(prefix = "myApp")
public class MyConfigProperties {
    private String someProperty;
    public String getSomeProperty() { return someProperty; }
    public void setSomeProperty(String someProperty) { this.setSomeProperty = setSomeProperty; }
}

When I tried to load someProperty, the value return by this key is always null. I couldn't figure out why is this happening. The bean property was injected correctly since the class MyConfigProperties is referenced correctly.

After some time of head banging and Googling, I realized that my service test class needs to know that MyConfigProperties is a ConfigurationProperties type.

The solution to this issue is to first create an application test class. This class is located at a directory higher than the rest of the test classes, and the test classes can load/specify this application test class as a configuration class. So, we create this file in:

src/test/java/com/packageName/

while the rest of the service test classes lives in:

src/test/java/com/packageName/service/

So, I created a TestApp class loaded with MyConfigProperties:

@EnableAutoConfiguration
@EnableConfigurationProperties(value = { MyConfigProperties.class })
public class TestApp {}

The main idea of @EnableConfigurationProperties is to look for a @ConfigurationProperties annotation in the MyConfigProperties and load this bean.

Now! A slight modification to our test service class, and we are done with this problem.

I then load the necessary context configuration such that my test profile knows which configuration class to load and proceeds to inject the necessary configuration files from it. The modified service class looks like:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestApp.class, initializers = ConfigFileApplicationContextInitializer.class)
public class SomeServiceTest {

    @Autowired
    private MyConfigProperties configProperties;
    
    @Test
    public void testPropertiesNotNull() {   
        Assertions.assertThat(
            configProperties.getSomeProperty())
            .isNotNull();
    }
}

Once I ran this test, I was so happy that it finally worked! Okay, it works, great, but why did this change made it work?

In our service test class, we specifically use @ContextConfiguration to allow us to load an ApplicationContext, in our case, TestApp.class that contains the necessary dependencies we need (configuration files). The initializers=ConfigFileApplicationContextInitializer.class specifically tells the loaded ApplicationContext to read configuration properties from our application.yml or application.properties file.

As quoted from the Spring docs:

ConfigFileApplicationContextInitializer is an ApplicationContextInitializer that you can apply to your tests to load Spring Boot application.properties files.

So there you have it! This was one out of the many moments that I struggle to find solutions from springdocs and stackoverflow.

As always, hope you enjoy reading, and more spring boot frustrations but happy yet fruitful learning experiences coming soon!