Java 在junit中模拟System.getenv调用时遇到问题

Java 在junit中模拟System.getenv调用时遇到问题,java,unit-testing,junit,Java,Unit Testing,Junit,我正试图用junit和mockito(这是非常新的)为Spring启动应用程序编写一个单元测试。基本上,在我的代码中,我为manifest.yml文件(用于部署)中的特定URL指定了一个环境变量,我可以通过代码中的String URL=System.getenv(“变量”)访问该文件。然而,我在单元测试中遇到了很多麻烦,因为URL变量显然是未定义的。我尝试了这个解决方案,但是意识到如果您是从实际测试本身调用环境变量,那么这只是为了模拟环境变量,而不是依赖于可以从代码访问的环境变量 有没有办法设置

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


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

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

我相信这说明了你正在努力实现的目标。 使用PowerMockito.spy()可能有一种更优雅的方法来实现这一点,我只是记不起来了


对于System.class中直接或间接被代码调用的所有其他方法,您需要执行
然后调用RealMethod()

这可以通过

您有两个选择:

EnvironmentVariables EnvironmentVariables=新的环境变量(“变量”)http://testurl");
//然后将测试代码放入execute方法中
环境变量。执行(()->{
//在这里,变量将包含测试值
});
//在这里,系统变量恢复正常
也可以使用JUnit4或JUnit5插件完成:

@ExtendWith(SystemStubsExtension.class)
类测试{
@系统存根
private EnvironmentVariables environment=新环境变量(“变量”)http://testurl");
@试验
无效测试(){
//在测试内部设置变量
//我们还可以更改环境变量:
环境。设定(“其他”、“价值”);
}
}

嘿,我不需要测试本身中的环境变量,我只需要它,这样当测试本身使用环境变量运行代码时,它将被定义为我设置的任何值。B/c现在是的,它是在测试中定义的,但是当测试执行它正在测试的实际代码时,它是未定义的。理解,我添加的代码只是演示System.getenv(“名称”)返回预期值的事实。当您的非单元测试代码调用System.getenv()时,您将看到类似的结果(即模拟系统将继续在您的非单元测试代码中工作)。所以,在您的单元测试中,有这样的行:
PowerMockito.when(System.getenv(Mockito.eq(“name”))。然后返回(“bart”)以设置您的环境。然后,您的非单元测试代码应该会看到这些值。如果这不起作用,请将问题发回,我可能可以帮助您解决它。嘿,它起作用了,但它在我的单元测试中导致了另一个错误。我得到以下错误
java.lang.ExceptionInInitializeError:java.lang.Integer.parseInt(Integer.java:454)处的null
这会干扰其他系统调用吗?是的,我们已经模拟了系统,我们需要做的是“间谍”系统(也称为部分模拟)。给我一分钟,我会帮你写密码。
@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"));
    }
}