I'd like to write some tests that check the XML Spring configuration of a deployed WAR. Unfortunately some beans require that some environment variables or system properties are set. How can I set an environment variable before the spring beans are initialized when using the convenient test style with @ContextConfiguration?
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:whereever/context.xml")
public class TestWarSpringContext { ... }
If I configure the application context with annotations, I don't see a hook where I can do something before the spring context is initialized.
This question is related to
java
spring
environment-variables
spring-test
You can set the System properties as VM arguments.
If your project is a maven project then you can execute following command while running the test class:
mvn test -Dapp.url="https://stackoverflow.com"
Test class:
public class AppTest {
@Test
public void testUrl() {
System.out.println(System.getProperty("app.url"));
}
}
If you want to run individual test class or method in eclipse then :
1) Go to Run -> Run Configuration
2) On left side select your Test class under the Junit section.
3) do the following :
For Unit Tests, the System variable is not instantiated yet when I do "mvn clean install" because there is no server running the application. So in order to set the System properties, I need to do it in pom.xml. Like so:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<configuration>
<systemPropertyVariables>
<propertyName>propertyValue</propertyName>
<MY_ENV_VAR>newValue</MY_ENV_VAR>
<ENV_TARGET>olqa</ENV_TARGET>
<buildDirectory>${project.build.directory}</buildDirectory>
</systemPropertyVariables>
</configuration>
</plugin>
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.
If you want your variables to be valid for all tests, you can have an application.properties
file in your test resources directory (by default: src/test/resources
) which will look something like this:
MYPROPERTY=foo
This will then be loaded and used unless you have definitions via @TestPropertySource
or a similar method - the exact order in which properties are loaded can be found in the Spring documentation chapter 24. Externalized Configuration.
One can also use a test ApplicationContextInitializer to initialize a system property:
public class TestApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
@Override
public void initialize(ConfigurableApplicationContext applicationContext)
{
System.setProperty("myproperty", "value");
}
}
and then configure it on the test class in addition to the Spring context config file locations:
@ContextConfiguration(initializers = TestApplicationContextInitializer.class, locations = "classpath:whereever/context.xml", ...)
@RunWith(SpringJUnit4ClassRunner.class)
public class SomeTest
{
...
}
This way code duplication can be avoided if a certain system property should be set for all the unit tests.
All of the answers here currently only talk about the system properties which are different from the environment variables that are more complex to set, esp. for tests. Thankfully, below class can be used for that and the class docs has good examples
A quick example from the docs, modified to work with @SpringBootTest
@SpringBootTest
public class EnvironmentVariablesTest {
@ClassRule
public final EnvironmentVariables environmentVariables = new EnvironmentVariables().set("name", "value");
@Test
public void test() {
assertEquals("value", System.getenv("name"));
}
}
Source: Stackoverflow.com