In the annotation @TestPropertySource you can add single properties using @TestPropertySource(properties = ["foo=bar"]).
With the annotation @PropertySource this is not supported.
I would expect the test annotation and the production annotation to work the same way.
In our case we want to add a configuration in a library, which should set a single property.
Hi Chicken Frau (@Huehnerlady),
Historically we have not seen a need for _inlined properties_ in production configuration classes. Rather, production configuration is typically externalized (e.g., from a properties file, JVM system properties, OS environment variables, etc.).
In other words, how would it benefit you to hard-code a property value via @PropertySource as opposed to either externalizing the value or hard-coding the value where the property is physically consumed/used?
@sbrannen the reason behind this is this stackoverflow question
We want to disable the rabbit health check without needing a application.yml for it. This should just happen if the mock Configuration is included - which is extracted in a lib.
The answers I got there so far is not sufficient for us, so I wanted to pursue the other idea we had - the inlining of that property into the configuration itself, which in my point of view is more readable as it is a single property. including a new file for that feels very heavy
Thanks for providing context with the SO question.
I understand that you would ideally like to have a _declarative_ solution; however, there are existing programmatic solutions that should work for you.
For example, you can add a custom PropertySource to the ConfigurableEnvironment in a @Configuration class constructor like this:
@SpringJUnitConfig
class PropertySourceTests {
@Test
void customPropertyAvailable(@Autowired Consumer consumer) {
assertThat(consumer.value).isEqualTo("bar");
}
@Configuration
static class Config {
Config(ConfigurableEnvironment environment) {
environment.getPropertySources().addFirst(new MapPropertySource("fooConfig",
Collections.singletonMap("foo", "bar")));
}
@Bean
Consumer consumer() {
return new Consumer();
}
}
static class Consumer {
@Value("${foo:default}")
String value;
}
}
Alternatively, you can register a custom PropertySourceFactory as follows.
Note: the value = "BOGUS" declaration is (unfortunately) necessary since Spring assumes any PropertySourceFactory will process the value/locations attribute, even though this example implementation completely ignores the @PropertySource annotation and its attributes.
@SpringJUnitConfig
class PropertySourceTests {
@Test
void customPropertyAvailable(@Autowired Consumer consumer) {
assertThat(consumer.value).isEqualTo("bar");
}
@Configuration
@PropertySource(factory = FooPropertySourceFactory.class, value = "BOGUS")
static class Config {
@Bean
Consumer consumer() {
return new Consumer();
}
}
static class Consumer {
@Value("${foo:default}")
String value;
}
static class FooPropertySourceFactory implements PropertySourceFactory {
@Override
public org.springframework.core.env.PropertySource<?> createPropertySource(
String name, EncodedResource resource) throws IOException {
return new MapPropertySource("fooConfig", Collections.singletonMap("foo", "bar"));
}
}
}
FYI: the Spring Boot team actually discourages the use of @PropertySource, as stated in the Spring Boot reference manual:
While using
@PropertySourceon your@SpringBootApplicationmay seem to be a convenient way to load a custom resource in theEnvironment, we do not recommend it. Such property sources are not added to theEnvironmentuntil the application context is being refreshed. This is too late to configure certain properties such aslogging.*andspring.main.*which are read before refresh begins.
I don't think inlining properties is something we should be encouraging via a production public API.
@huehnerlady I've replied to your stackoverflow question.
I agree with @snicoll. In light of that and the elegant solution he posted on SO, I am closing this issue.
Many thanks for your help
Most helpful comment
I don't think inlining properties is something we should be encouraging via a production public API.
@huehnerlady I've replied to your stackoverflow question.