JMock - 如何模拟控制台输出

时间:2012-04-21 19:07:31

标签: java junit jmock

这篇文章类似于:this

我有一个控制台应用程序,它需要用户输入并具有响应式用户输出。我正在为它编写一些单元测试,以确保代码正常工作。我需要能够确保它的输出和输入符合我的期望。

基本上,我有一个主要方法正在测试,要求输入文件或输入。在我的测试中,我使用System.setOutSystem.setIn分别将它们设置为PrintStream和InputStream对象的context.mock版本。在我将测试结果输出到控制台时,我必须测试程序数据的实际处理,我不关心System.out.println调用的内容。总结一下:

这是我的来源正在接受测试(一些接近,我修剪得很多):http://ideone.com/rptC0

以下是我在模拟程序中的内容:http://ideone.com/VkvqM

这是我得到的例外:ideone.com/OEOS8

正如你可以清楚地看到我的期望,我明确地说我打算打印完全相同的字符串,并且我在我的期望中指明了这一点。但例外情况表明这是出乎意料的。我不明白......

1 个答案:

答案 0 :(得分:0)

JMock希望您使用context.checking() 声明期望然后调用正在测试的代码,然后调用context.assertIsSatisfied()(尽管有时候是最后一步如果使用适当的测试运行器,则隐式完成。

您似乎在运行任何代码之前立即调用context.assertIsSatisfied()

此外,您发布的代码使用的变量mn似乎没有定义 - 实际上是您正在运行的代码?或者该变量应该是mockIn

已更新:好的,问题可能是您尝试模拟静态方法 - JMock不支持此操作 - 请参阅jmock mocking a static method。特别是Steve Freeman的回答,他是JMock的作者之一。

更新2 :我会尝试这样的事情,在@Before设置中设置期望:

@Before
public void setMinimalMockingExpectations() throws IOException
{
    oldIn = System.in;
    oldOut = System.out;
    pipe = new PipedOutputStream();
    testIn = new PipedInputStream(pipe);
    mockOut = context.mock(PrintStream.class);
    System.setOut(mockOut);
    System.setIn(testIn);

    expectQuestion();
}

private void expectQuestion()
{
    Expectations exp = new Expectations()
    {
        {
            one(mockOut).println(main.QUESTION);
        }
    };
    context.checking(exp);

}

@After
public void reset()
{
    System.setIn(oldIn);
    System.setOut(oldOut);
}

@Test
public void fileChoiceReturnsFalse() throws IOException
{
    String FILE = "F\n";
    pipe.write(FILE.getBytes());

    assertFalse(main.promptStringOrFile());

    context.assertIsSatisfied(); // can avoid this call by using the right
                                    // test runner
}

并创建两个类似的测试来检查输入“I”和任何其他输入的行为(问题应该重复一次)。

如果使用promptStringOrFile()而不是担心字符,BufferedReader.readLine()方法可能更清晰。