20

任何人都可以就如何最好地使用 EasyMock 来期待电话提出任何建议Runtime.getRuntime().exec(xxx)吗?

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

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

interface ProcessWrapper {
    int waitFor() throws InterruptedException;
}

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

4

4 回答 4

15

你的班级不应该打电话给Runtime.getRuntime(). 它应该期望 aRuntime被设置为其依赖项,并使用它。然后在您的测试中,您可以轻松地提供一个模拟并将其设置为依赖项。

作为旁注,我建议观看关于 OO Design for testability 的讲座

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

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

于 2010-02-13T14:48:18.643 回答
8

上面的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();
    }
}
于 2010-02-15T14:50:29.690 回答
1

Runtime.getRuntime().exec()也许您可以“模拟”脚本/程序/等而不是嘲笑。它应该在打电话。

不要将真正的命令行字符串传递给 ,而是exec()编写一个测试脚本并执行它。您可以让脚本返回您可以测试的硬编码值,就像模拟类一样。

于 2010-02-13T20:52:08.170 回答
0

以下是使用 EasyMock 3.0(和 JUnit 4)的方法:

import org.junit.*;
import org.easymock.*;
import static org.easymock.EasyMock.*;

public final class EasyMockTest extends EasyMockSupport
{
    @Test
    public void mockRuntimeExec() throws Exception
    {
         Runtime r = createNiceMock(Runtime.class);

         expect(r.exec("command")).andReturn(null);
         replayAll();

         // In tested code:
         r.exec("command");

         verifyAll();
    }
}

上面测试的唯一问题是Runtime对象需要传递给被测代码,这会阻止它使用Runtime.getRuntime(). 另一方面,使用JMockit可以编写以下测试,避免该问题:

import org.junit.*;
import mockit.*;

public final class JMockitTest
{
    @Test
    public void mockRuntimeExec() throws Exception
    {
        final Runtime r = Runtime.getRuntime();

        new NonStrictExpectations(r) {{ r.exec("command"); times = 1; }};

       // In tested code:
       Runtime.getRuntime().exec("command");
    }
}
于 2010-08-30T13:37:31.410 回答