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.
Comment From: sbrannen
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?
Comment From: huehnerlady
@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
Comment From: sbrannen
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;
}
}
Comment From: sbrannen
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"));
}
}
}
Comment From: sbrannen
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.
Comment From: snicoll
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.
Comment From: sbrannen
I agree with @snicoll. In light of that and the elegant solution he posted on SO, I am closing this issue.
Comment From: huehnerlady
Many thanks for your help