Issue
This is my first time working with Externalized Configuration and yaml.
I created a yaml where I use the class name as KEY, and the field name as VALUE
YAML:
# test placeholders
project:
test:
service:
computator:
# exclude field from beeing randomly valorized
population:
exclude:
InputClass: 'myDate'
AnotherClass: 'myName'
ExcludePopulationProperties:
@Data
@Component
@ConfigurationProperties(prefix = "project")
public class ExcludePopulationProperties {
private Test test;
@Data
public static class Test {
private Service service;
}
@Data
public static class Service {
private Computator computator;
}
@Data
public static class Computator {
private Population population;
}
@Data
public static class Population {
private Map<String, String> exclude;
}
}
Test with JUnit 5:
@ContextConfiguration(classes = { ExcludePopulationProperties.class })
@ExtendWith(SpringExtension.class)
class YamlTest {
@Autowired
private ExcludePopulationProperties excludePopulationProperties;
@Test
void testExternalConfiguration() {
Map<String, String> map = excludePopulationProperties.getTest().getService().getComputator().getPopulation().getExclude();
assertNotNull(map);
}
The problem is that I have a NullPointerException because test is null
So I'm not sure what is wrong here, I was expecting that the map was correctly populated.
I also tried to add
@TestPropertySource(properties = { "spring.config.location=classpath:application-_test.yaml" })
on the YamlTest
Solution
With these little changes, now I'm able to test the property value from YAML file.
I improved the yaml a little bit:
# test placeholders
project:
test:
service:
computator:
# exclude field from beeing randomly valorized
population:
exclude:
InputClass:
- 'myDate'
AnotherClass:
- 'myName'
so now the ExcludePopulationProperties have a Map<String, List<String>> instead of Map<String, String>, in this way I will be able to exclude more than one field from the same class:
@Data
@Configuration
@ConfigurationProperties(prefix = "project")
@PropertySource(value = "classpath:application-_test.yaml", factory = YamlPropertySourceFactory.class)
public class ExcludePopulationProperties {
private Test test;
@Data
public static class Test {
private Service service;
}
@Data
public static class Service {
private Computator computator;
}
@Data
public static class Computator {
private Population population;
}
@Data
public static class Population {
private Map<String, List<String>> exclude;
}
}
YamlPropertySourceFactory is a class implemented by Baeldung in this guide: @PropertySource with YAML Files in Spring Boot
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
Properties properties = factory.getObject();
return new PropertiesPropertySource(resource.getResource().getFilename(), properties);
}
}
Test Class :
@EnableConfigurationProperties
@ContextConfiguration(classes = { ExcludePopulationProperties.class })
@TestPropertySource(properties = { "spring.config.location=classpath:application-_test.yaml" })
@ExtendWith(SpringExtension.class)
class YamlTest {
@Autowired
private ExcludePopulationProperties excludePopulationProperties;
@Test
void testExternalConfiguration() {
Map<String, List<String>> map = excludePopulationProperties.getTest().getService().getComputator().getPopulation().getExclude();
assertNotNull(map);
}
}
Please note that for Mockito you need to use both, SpringExtension and MockitoExtension:
@EnableConfigurationProperties
@ContextConfiguration(classes = { ExcludePopulationProperties.class })
@Extensions({
@ExtendWith(SpringExtension.class),
@ExtendWith(MockitoExtension.class)
})
class YamlTest {
}
Answered By - Paul Marcelin Bejan
Answer Checked By - David Goodson (JavaFixing Volunteer)