Mock java.lang.Runtime with PowerMockito

 ̄綄美尐妖づ 提交于 2019-12-07 04:11:54

问题


want to write an unittest for a method like

public static void startProgram() {
    process = Runtime.getRuntime().exec(command, null, file);
}

I don't want to inject the runtime object for some reasons, so I wanted to stub the getRuntime method that it returns a Runtime mock... I tried it this way:

@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
    }
}

But this doesn't work. Actually nothing seems to be mocked. In the test the normal Runtime object is used.

Anyone any idea why this doesn't work and/or how it works?

As this mini example seems not to reproduce the problem here is the full test code: method to test (shortened)

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;
}

and the test:

@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");
}

Then, in the test, the call to Runtime.getRuntime() doesn't bring the mock and that's why an IOException is thrown because the String is no directory...


回答1:


My bad in the comments, apologies, I had an inner class for the test and that's why I had no trouble. I then realized this and saw your @PrepareForTest(Runtime.class) which should read @PrepareForTest(MyClass.class) (replace MyClass with whatever name you have) because Runtime is a system class. You can read more about this here and find more examples here.




回答2:


You must write a wrapper class for Runtime, because it's system class.

public class AppShell {
  public Process exec(String command) {
    return Runtime.getRuntime().exec(command);
  }
}

Then in unit test, use @PrepareForTest(AppShell.class) instead of @PrepareForTest(Runtime.class)

@RunWith(PowerMockRunner.class)
@PrepareForTest(AppShell.class)
public class AppShellTest {

    @Mock private Runtime mockRuntime;

    @Test
    public void test() {
        PowerMockito.mockStatic(Runtime.class);

        when(Runtime.getRuntime()).thenReturn(mockRuntime);
        when(mockRuntime.exec()).thenReturn("whatever you want");

        // do the rest of your test
    }
}

See PowerMock - Mocking system classes



来源:https://stackoverflow.com/questions/24039184/mock-java-lang-runtime-with-powermockito

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!