加载系统属性进行测试

发布于 2024-10-05 09:19:04 字数 1338 浏览 0 评论 0原文

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

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

可遇━不可求 2024-10-12 09:19:04

一些想法:

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

A few ideas:

  1. 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.
  2. 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.
  3. Setting system properties from a file is rather wrong anyways. Normally you would use System properties to override settings in the properties file.
长亭外,古道边 2024-10-12 09:19:04

问题实际上是 Properties 类中的值是静态定义的。因此,这里是破坏解决方案的情况:

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

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

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.

末蓝 2024-10-12 09:19:04

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文