Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 模拟运行时。getRuntime()?_Java_Unit Testing_Junit_Easymock_Runtime.exec - Fatal编程技术网

Java 模拟运行时。getRuntime()?

Java 模拟运行时。getRuntime()?,java,unit-testing,junit,easymock,runtime.exec,Java,Unit Testing,Junit,Easymock,Runtime.exec,有人能就如何最好地使用EasyMock来期望调用Runtime.getRuntime().exec(xxx)提出建议吗 我可以将调用移动到另一个实现接口的类中的方法中,但最好不要在理想情况下 interface RuntimeWrapper { ProcessWrapper execute(String command) throws IOException; } interface ProcessWrapper { int waitFor() throws Interrupt

有人能就如何最好地使用EasyMock来期望调用
Runtime.getRuntime().exec(xxx)
提出建议吗

我可以将调用移动到另一个实现接口的类中的方法中,但最好不要在理想情况下

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

interface ProcessWrapper {
    int waitFor() throws InterruptedException;
}

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

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

作为旁注,我建议看一看

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


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

也许您可以“模拟”脚本/程序等,而不是模拟
Runtime.getRuntime().exec()

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

以上是正确的解决方案。但这不是唯一的解决办法。你可以使用或

使用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();
    }
}

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

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

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

谢谢你的建议——我同意注入依赖性是最好的方法,但我更喜欢嘲笑它。然而,我看不到一种获得模拟运行时实例的方法——它不是一个接口,而且我不确定我是否可以将其子类化,因为它有一个私有构造函数。也许我遗漏了什么?我将使用包装器方法:)再次感谢!这是我一开始尝试的,但我发现了一些问题。首先,它打破了测试的平台独立性(即使代码是为Windows设计的,测试通常在Linux机器上运行),其次,出于某种原因,它让我害怕模仿脚本。可能是因为我害怕签入:)另外,模拟运行时让我更容易模拟不同的场景。无论如何谢谢你!谢谢你的建议,我以前从未听说过Powermock。
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");
    }
}