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!