使用PowerMockito模拟java.lang.Runtime

Jog*_*ogi 5 java junit mockito powermock

想为像这样的方法编写单元测试

public static void startProgram() {
    process = Runtime.getRuntime().exec(command, null, file);
}
Run Code Online (Sandbox Code Playgroud)

我不想因为某些原因注入运行时对象,所以我想将getRuntime方法存根,它返回一个Runtime mock ...我试过这样:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Runtime.class)
public class ProgramTest {

    @Test
    public void testStartProgram() {
        Runtime mockedRuntime = PowerMockito.mock(Runtime.class);

        PowerMockito.mockStatic(Runtime.class);
        Mockito.when(Runtime.getRuntime()).thenReturn(mockedRuntime);

        ... //test
    }
}
Run Code Online (Sandbox Code Playgroud)

但这不起作用.实际上似乎没有任何东西被嘲笑.在测试中,使用正常的Runtime对象.

任何人都知道为什么这不起作用和/或它是如何工作的?

由于这个小例子似乎没有重现问题,这里是完整的测试代码:测试方法(缩短)

public static synchronized long startProgram(String workspace) {
    // Here happens someting with Settings which is mocked properly
    File file = new File(workspace);
    try {
        process = Runtime.getRuntime().exec(command, null, file);
    } catch (IOException e) {
        throw e;
    }
    return 0L;
}
Run Code Online (Sandbox Code Playgroud)

和测试:

@Test
public void testStartProgram() {
    PowerMockito.mockStatic(Settings.class);
    Mockito.when(Settings.get("timeout")).thenReturn("42");

    Runtime mockedRuntime = Mockito.mock(Runtime.class);
    // Runtime mockedRuntime = PowerMockito.mock(Runtime.class); - no difference
    Process mockedProcess = Mockito.mock(Process.class);

    Mockito.when(mockedRuntime.exec(Mockito.any(String[].class), Mockito.any(String[].class),
                    Mockito.any(File.class))).thenReturn(mockedProcess);

    PowerMockito.mockStatic(Runtime.class);
    Mockito.when(Runtime.getRuntime()).thenReturn(mockedRuntime);

    startProgram("doesnt matter");
}
Run Code Online (Sandbox Code Playgroud)

然后,在测试中,对Runtime.getRuntime()的调用不会带来模拟,这就是抛出IOException的原因,因为String不是目录...

Mor*_*fic 5

我的评论不好,抱歉,我有一个内部课程用于测试,这就是为什么我没有遇到任何麻烦。然后我意识到了这一点,并看到您的@PrepareForTest(Runtime.class)which 应该读取@PrepareForTest(MyClass.class)(用您拥有的任何名称替换 MyClass )因为Runtimeis a system class。你可以阅读更多关于这个在这里找到更多的例子在这里