Keywords: Spring Testing | @TestPropertySource | PropertySourcesPlaceholderConfigurer
Abstract: This paper comprehensively examines the property loading failures encountered when using the @TestPropertySource annotation in Spring 4.1.17 and Spring Boot 1.2.6.RELEASE environments. Through analysis of official documentation and practical code examples, it reveals the core mechanism where @Value annotations depend on the PropertySourcesPlaceholderConfigurer Bean for placeholder resolution. The article systematically compares different solutions and provides validated configuration approaches to help developers avoid common testing environment pitfalls.
In Spring framework testing environments, correct property configuration loading is crucial for ensuring unit test reliability. However, many developers encounter property injection failures when combining the @TestPropertySource annotation with AnnotationConfigContextLoader, typically manifested as unresolved placeholders in @Value annotations outputting raw strings like ${elastic.index}.
Root Cause Analysis
According to Spring official documentation and community experience, the primary function of the @TestPropertySource annotation is to add or override property sources in test contexts. However, in certain version combinations, particularly Spring 4.1.x with Spring Boot 1.2.x, this annotation may not integrate perfectly with Java-configured test contexts. The core issue lies in the @Value annotation requiring a PropertySourcesPlaceholderConfigurer Bean to resolve ${...} formatted placeholders, which may not be provided by default test configurations.
Detailed Solution
The most effective solution involves explicitly defining a PropertySourcesPlaceholderConfigurer Bean in the test configuration class. The following code example demonstrates proper configuration:
@Configuration
public class TestConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
In the test class, import this configuration via the @Import annotation:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@TestPropertySource(properties = {"elastic.index=test_index"})
public class PropertyTest {
@Configuration
@Import(TestConfig.class)
static class ContextConfiguration {}
@Value("${elastic.index}")
private String index;
@Test
public void testPropertyInjection() {
assertEquals("test_index", index);
}
}
Version Compatibility Notes
It's important to note that this issue has been officially fixed in Spring Boot version 1.4.0 and above. Relevant commit records indicate that the fix ensures properties declared in @TestPropertySource receive highest precedence. For developers still using older versions, manual configuration of PropertySourcesPlaceholderConfigurer remains a reliable temporary solution.
Additional Considerations
Beyond the core solution, several practical considerations should be noted:
- Avoid mixing locations and properties parameters in @TestPropertySource, as this may lead to undefined behavior.
- Ensure property files use .properties format rather than .yaml, since @TestPropertySource doesn't support direct YAML file loading.
- For complex multi-environment configurations, consider using Spring Profiles or custom PropertySource implementations.
Conclusion
By deeply understanding Spring's property resolution mechanisms, developers can avoid common configuration errors in testing. The key insight recognizes the central role of PropertySourcesPlaceholderConfigurer in placeholder resolution and selects appropriate configuration strategies based on actual versions. As the Spring ecosystem continues evolving, timely dependency updates are recommended to benefit from the latest feature improvements and bug fixes.