Mock Runtime.getRuntime()?

任何人都可以提出任何关于如何最好地使用EasyMock来期待呼叫的建议?Runtime.getRuntime().exec(xxx)

我可以将调用移动到另一个实现接口的类中的方法中,但宁愿不在理想的世界中。

interface RuntimeWrapper {
    ProcessWrapper execute(String command) throws IOException;
}

interface ProcessWrapper {
    int waitFor() throws InterruptedException;
}

我想知道是否有人有其他建议?


答案 1

您的类不应调用 。它应该期望将 a 设置为其依赖项,并使用它。然后在测试中,您可以轻松提供模拟并将其设置为依赖项。Runtime.getRuntime()Runtime

顺便说一句,我建议观看这个关于OO设计的可测试性讲座

更新:我没有看到私有构造函数。您可以尝试使用java字节码检测来添加另一个构造函数或使构造函数公开,但这也可能是不可能的(如果对该类有一些限制)。

所以你的选择是做一个包装器(正如你在问题中建议的那样),并遵循依赖注入方法。


答案 2

上面的Bozho是IMO的正确解决方案。但这并不是唯一的解决方案。你可以使用PowerMockJMockIt

使用PowerMock:

package playtest;

public class UsesRuntime {
    public void run() throws Exception {
        Runtime rt = Runtime.getRuntime();
        rt.exec("notepad");
    }
}


package playtest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;

import static org.powermock.api.easymock.PowerMock.*;
import static org.easymock.EasyMock.expect;

@RunWith(PowerMockRunner.class)
@PrepareForTest( { UsesRuntime.class })
public class TestUsesRuntime {

    @Test
    public void test() throws Exception {
        mockStatic(Runtime.class);
        Runtime mockedRuntime = createMock(Runtime.class);

        expect(Runtime.getRuntime()).andReturn(mockedRuntime);

        expect(mockedRuntime.exec("notepad")).andReturn(null);

        replay(Runtime.class, mockedRuntime);

        UsesRuntime sut = new UsesRuntime();
        sut.run();
    }
}

推荐