3

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

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

@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 都已成功从上下文中拉出。但是,这些属性没有被正确加载,因为当我尝试访问它们时它们都为空。有什么建议么?

4

3 回答 3

3

一些想法:

  1. 如果您是单元测试,那么为什么不在每个单独的测试用例中设置所需的属性。使用 spring 设置全局变量是没有意义的。
  2. 为什么要使用系统属性。Spring 管理可以注入到 bean 中的属性对象。它们可以在 appContext.xml 中设置,也可以使用系统属性在那里初始化(参见:PropertyPlaceHolderConfigurer)。让您的代码访问系统属性是违反 spring 的哲学的。
  3. 无论如何,从文件设置系统属性是相当错误的。通常您会使用系统属性来覆盖属性文件中的设置。
于 2010-11-30T17:34:37.520 回答
2

问题实际上是来自 Properties 类的值是静态定义的。所以这是打破解决方案的案例:

  1. 运行测试 A。测试 A 不会加载 applicationContext-test.xml,但它调用使用 Properties 类中的值的代码。
  2. 现在,Properties 类的所有值都被永久定义。
  3. 运行测试 B。测试 B 加载 applicationContext-test.xml。
  4. SystemPropertiesLoader 运行,将值加载到系统属性中。
  5. 一个值是从 Properties 类中检索的,但由于它们是静态定义并先前分配的,系统属性中的值永远不会进入那里。

最后,最好的解决方案是在 Properties 类中定义默认值。

于 2010-12-06T22:34:33.787 回答
0

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

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

于 2010-11-30T17:33:41.370 回答