无法在junit中模拟System.getenv调用

时间:2017-09-19 01:39:51

标签: java unit-testing junit

我正在尝试使用junit和mockito(非常新的)为Spring Boot应用程序编写单元测试。基本上在我的代码中,我为manifest.yml文件(用于部署)中的特定URL指定了一个环境变量,我可以通过代码中的String URL = System.getenv("VARIABLE")访问该文件。但是,我的单元测试遇到了很多麻烦,因为URL变量显然是未定义的。我尝试了解决方案here,但意识到这只是为了模拟环境变量,如果您从实际测试本身调用它,而不是如果您依赖于可从中访问的环境变量代码。

有没有办法设置它,以便在运行测试时,我可以设置可以在代码中访问的环境变量?

2 个答案:

答案 0 :(得分:4)

您可以使用PowerMockito来模拟静态方法。此代码演示了模拟System类和存根getenv()

@RunWith(PowerMockRunner.class)
@PrepareForTest({System.class})
public class Xxx {

    @Test
    public void testThis() throws Exception {
        System.setProperty("test-prop", "test-value");
        PowerMockito.mockStatic(System.class);

        PowerMockito.when(System.getenv(Mockito.eq("name"))).thenReturn("bart");
        // you will need to do this (thenCallRealMethod()) for all the other methods
        PowerMockito.when(System.getProperty(Mockito.any())).thenCallRealMethod();

        Assert.assertEquals("bart", System.getenv("name"));

        String value = System.getProperty("test-prop");

        Assert.assertEquals("test-value", System.getProperty("test-prop"));
    }
}

我相信这说明了你想要实现的目标。 可能使用PowerMockito.spy()做一个更优雅的方法,我就是记不住了。

对于System.class中直接或间接调用的所有其他方法,您需要thenCallRealMethod()

答案 1 :(得分:0)

这可以通过https://github.com/webcompere/system-stubs

来实现

您有两种选择:

EnvironmentVariables environmentVariables = new EnvironmentVariables("VARIABLE", "http://testurl");

// then put the test code inside an execute method
environmentVariables.execute(() -> {
   // inside here, the VARIABLE will contain the test value
});

// out here, the system variables are back to normal

或者可以使用JUnit4或5插件来完成:

@ExtendWith(SystemStubsExtension.class)
class SomeTest {

    @SystemStub
    private EnvironmentVariables environment = new EnvironmentVariables("VARIABLE", "http://testurl");

    @Test
    void someTest() {
        // inside the test the variable is set
        // we can also change environment variables:

        environment.set("OTHER", "value");
    }

}