使用依赖于环境变量的代码进行单元测试

时间:2011-07-14 13:26:10

标签: ant junit environment-variables

我们暴露了一小组环境变量来控制我们的应用程序行为。应用程序代码在java中。 (环境变量可能是邪恶的,但在这种特殊情况下有目的)

对此进行单元测试的最佳方法是什么?如何创建环境变量,将其设置为不同的值并重复调用测试?

目前的解决方案是在junit任务中使用env元素。例如下面

 <env key="BASE_PLUGINS_FOLDER" value="c:/temp"/>

代码为测试设置环境变量。 (仅当fork模式设置为true时才有效)

这意味着我必须在ant构建文件中创建多个测试部分,并在其他地方测试相应的测试部分。这可能会很快变得无法管理。

我觉得可能有更好的方法,那就是完整的junit-java代码。不确定如何。

4 个答案:

答案 0 :(得分:8)

您应该封装检索这些变量的方式。它不仅允许您更改传递方式(env变量,系统属性,配置文件等等),而且还可以更加可测试。

然后,您可以定义两个不同的实现:一个实际读取环境(您在生产中使用),另一个您可以在Java中自己指定这些值(在测试中使用)。

答案 1 :(得分:3)

这是我朋友给的黑客..

            Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
        Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
        theEnvironmentField.setAccessible(true);
        @SuppressWarnings({"unchecked"}) // this will be a Map or the test will fail if Java internals are changed
                Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
        env.put(name, val);

        // now System.getenv will return what we want
        //noinspection CallToSystemGetenv
        assertEquals("Problems setting up environment variable for test: " + name, val, System.getenv(name));

答案 2 :(得分:1)

我担心这是一个无用的,令人沮丧的答案......但考虑重新设计应用程序以允许覆盖环境变量。

所有对它们的访问都需要通过一个地方汇集,这也可以寻找您选择的配置机制 -
-D,
或财产档案,
或-d,
指向的属性文件 或测试设置传递的运行时创建的配置对象,
或烟雾信号,
或者......

答案 3 :(得分:0)

这可以使用 JUnit 4 和 JUnit 5 中的系统存根 (https://github.com/webcompere/system-stubs) 解决:

JUnit 4:

@Rule
public EnvironmentVariablesRule env = new EnvironmentVariablesRule("BASE_PLUGINS_FOLDER", "/tmp/something");

@Test
public void test() {
   // variable is set here
}

或者在 JUnit 5 中:

@ExtendWith(SystemStubsExtension.class)
class SomeTest {

    @SystemStub
    private EnvironmentVariables env = new EnvironmentVariables("BASE_PLUGINS_FOLDER", "/tmp/something");

    @Test
    void envSetHere() {
        // environment variable is set
    }
}