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;开发者_C百科
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?
A few ideas:
- If you are unit testing, so why not set the required properties in each individual test case. There is no point using spring to set a global variable.
- Why do you use system properties. Spring manages property objects that you can inject into you beans. They can be setup in the appContext.xml and also be initialised there (see: PropertyPlaceHolderConfigurer) using System properties. Having your code access System properties is against the very philosophy of spring.
- Setting system properties from a file is rather wrong anyways. Normally you would use System properties to override settings in the properties file.
The problem was actually that the values from the Properties class were defined statically. So here's the case that broke the solution:
- 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.
- Now, all values from the Properties class are defined permanently.
- Test B is run. Test B loads applicationContext-test.xml.
- The SystemPropertiesLoader is run, loading values into system properties.
- 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.
Could it be possible that each of your test cases is spawning a new JVM, and the System
properties are not being set for each test case?
Maybe try to leverage the setUp()
and tearDown()
methods in your JUnit test class.
精彩评论