Spring @TestPropertySource
The right way to do this, starting with Spring 4.1, is to use a @TestPropertySource
annotation.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:whereever/context.xml")
@TestPropertySource(properties = {"myproperty = foo"})
public class TestWarSpringContext {
...
}
See @TestPropertySource
in the Spring docs and Javadocs.
Dynamic Properties
If the property is dynamic e.g. a hostname or port from a dynamically created testcontainer, the @DynamicPropertySource
annotation can be used. Example with a kafka TestContainer that exposes the container's bootstrap servers:
@DynamicPropertySource
static void kafkaProperties(DynamicPropertyRegistry registry) {
registry.add("spring.kafka.bootstrap-servers", kafka::getBootstrapServers);
}
See @DynamicPropertySource
in the Spring docs and Javadocs.
A Note on Spring Environment Properties vs Environment Variables and System Properties
One popular comment below says:
This provides an Environment property, which is different to an "Environment variable". –
Yes, that's true, BUT if you are using Spring, you shouldn't be directly accessing environment variables or system properties in your code. Spring provides an abstraction over property sources such as configuration files, system properties, and environment variables called the Spring PropertySource. Since code in a Spring environment should be using this abstraction, this is the proper way to inject these properties, bypassing the direct access of environment variables entirely.
If you have a 3rd party library or something that is using environment variables, and you can't abstract or mock that code for your test, then you have a completely different problem, requiring a different non-Spring-specific solution.