加载测试的系统属性

时间:2010-11-30 17:17:14

标签: java spring-mvc junit4 system-properties

我最近找到了一个允许我为单元测试加载系统属性的解决方案。如果我单独运行测试,它会很有效,但如果我选择运行整个测试套件,它就会失败。有人可以告诉我为什么吗?

第一步是加载测试应用程序上下文:

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

下一步是创建一个将加载系统属性的类:

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();
        }
    }
}

最后一步是在我的测试应用程序上下文中将其列为bean:

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

当我运行测试套件时,我的几个测试都失败了,所有测试都依赖于系统属性。如果我去进行特定测试并运行它,它将通过。我调试了它,我已经验证了SystemPropertiesLoader中的代码正在执行,并且所有其他bean都是从上下文中成功提取的。但是,属性没有正确加载,因为当我尝试访问它们时它们都是null。有什么建议吗?

3 个答案:

答案 0 :(得分:3)

一些想法:

  1. 如果您是单元测试,那么为什么不在每个单独的测试用例中设置所需的属性。使用spring设置全局变量没有意义。
  2. 为什么使用系统属性。 Spring管理可以注入bean的属性对象。它们可以在appContext.xml中设置,也可以使用系统属性在那里初始化(参见:PropertyPlaceHolderConfigurer)。让你的代码访问系统属性违背了spring的理念。
  3. 无论如何,从文件设置系统属性都是错误的。通常,您将使用系统属性覆盖属性文件中的设置。

答案 1 :(得分:2)

问题实际上是Properties类中的值是静态定义的。所以这就是打破解决方案的情况:

  1. 运行测试A.测试A不加载applicationContext-test.xml,但 调用使用Properties类中的值的代码。
  2. 现在,Properties类中的所有值都是永久定义的。
  3. 运行测试B.测试B加载applicationContext-test.xml。
  4. 运行SystemPropertiesLoader,将值加载到系统属性中。
  5. 从Properties类中检索一个值,但由于它们是静态定义的并且之前已分配过,因此系统属性中的值永远不会进入。
  6. 最后,最好的解决方案是在Properties类中定义默认值。

答案 2 :(得分:0)

您的每个测试用例是否可能产生新的JVM,并且没有为每个测试用例设置System属性?

也许尝试利用JUnit测试类中的setUp()和tearDown()方法。