Search code examples
javaspring-mvcjunit4system-properties

Loading system properties for tests


I recently found a solution that allows me to load system properties for my unit tests. It works great if I'm running a test individually, but if I choose to run the whole test suite, it fails. Can someone tell me why?

The first step is to load the test application context:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/applicationContext-test.xml")

The next step is to create a class which will load the system properties:

import java.io.InputStream;
import java.util.Properties;

import javax.annotation.PostConstruct;

import org.springframework.core.io.Resource;

public class SystemPropertiesLoader{

    private Resource resource;

    public void setResource(final Resource resource){
        this.resource = resource;
    }

    @PostConstruct
    public void applyProperties() throws Exception{

        final Properties systemProperties = System.getProperties();

        final InputStream inputStream = resource.getInputStream();

        try{
            systemProperties.load(inputStream);
        } finally{
            inputStream.close();
        }
    }
}

The final step is to list this as a bean in my test application context:

<bean class="com.foo.SystemPropertiesLoader">
    <property name="resource" value="classpath:localdevelopment_Company.properties" />
</bean>

When I run the test suite, several of my tests, all of which rely on system properties, fail. If I go to the specific test and run it, it will pass. I've debugged it and I've verified that the code in SystemPropertiesLoader is being executed, and all other beans are being pulled successfully from the context. However, the properties are not being loaded correctly, as they are all coming up null when I try to access them. Any suggestions?


Solution

  • The problem was actually that the values from the Properties class were defined statically. So here's the case that broke the solution:

    1. Test A is run. Test A does not load applicationContext-test.xml but it does call into code that uses values from the Properties class.
    2. Now, all values from the Properties class are defined permanently.
    3. Test B is run. Test B loads applicationContext-test.xml.
    4. The SystemPropertiesLoader is run, loading values into system properties.
    5. A value is retrieved from the Properties class, but since they were defined statically and assigned previously, the values from system properties never get in there.

    In the end, the best solution was to define default values within the Properties class.