有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

junit模拟java。lang.Runtime与PowerMockito

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

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

出于某些原因,我不想注入运行时对象,所以我想存根getRuntime方法,使其返回运行时模拟。。。我这样试过:

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

但这不管用。事实上,似乎没有什么可以嘲笑的。在测试中,使用普通运行时对象

有人知道这为什么不起作用和/或它是如何起作用的吗

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

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

而测试:

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

然后,在测试中,调用Runtime。getRuntime()不会带来模拟,这就是为什么会抛出IOException,因为字符串不是目录


共 (2) 个答案

  1. # 1 楼答案

    我的错误在于我的评论、道歉,我有一个考试的内部课程,这就是为什么我没有遇到任何问题。然后我意识到了这一点,并看到您的@PrepareForTest(Runtime.class)应该是@PrepareForTest(MyClass.class)(用您拥有的任何名称替换MyClass),因为Runtime是一个系统类。你可以阅读更多关于这个here的内容,并找到更多的例子here

  2. # 2 楼答案

    必须为Runtime编写一个包装器类,因为它是系统类

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

    然后在单元测试中,使用@PrepareForTest(AppShell.class)而不是@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
        }
    }
    

    PowerMock - Mocking system classes