我们如何模拟Ctrl+;C停止控制台应用程序在java中等待用户输入

我们如何模拟Ctrl+;C停止控制台应用程序在java中等待用户输入,java,Java,我正在尝试测试一个命令行应用程序,它在每个步骤后都会等待用户输入。我能够使用Stefan Birkner提供的测试应用程序。目前,我从开始到结束提供输入,这就像一个符咒,我可以断言系统日志的最终输出 但是,我想在应用程序结束之前测试负面情况,我在开始时为其提供无效输入以评估错误消息。当给出无效输入时,控制台将打印一条错误消息,并一直等待用户提供有效输入。如何使用Ctrl+C发送,如下所示: @Test public void testInValidMarker() throws Exceptio

我正在尝试测试一个命令行应用程序,它在每个步骤后都会等待用户输入。我能够使用Stefan Birkner提供的测试应用程序。目前,我从开始到结束提供输入,这就像一个符咒,我可以断言系统日志的最终输出

但是,我想在应用程序结束之前测试负面情况,我在开始时为其提供无效输入以评估错误消息。当给出无效输入时,控制台将打印一条错误消息,并一直等待用户提供有效输入。如何使用Ctrl+C发送,如下所示:

@Test
public void testInValidMarker() throws Exception{
    systemInMock.provideLines("abc","def","1");
    Main.main(new String[]{});
    assertTrue(systemOutRule.getLog().contains("Invalid marker, try again"));
}
systemInMock.provideLines(Ctrl+C)

systemInMock.provideLines仅接受字符串。有没有办法发送Ctrl+C信号

我的junit测试示例如下所示:

@Test
public void testInValidMarker() throws Exception{
    systemInMock.provideLines("abc","def","1");
    Main.main(new String[]{});
    assertTrue(systemOutRule.getLog().contains("Invalid marker, try again"));
}

谢谢你的帮助

如果我没记错的话,当您执行ctrl+c时,它实际上不会写入控制台。如果这是真的,那么您的程序在任何情况下都不会被赋予ctrl+c,因此
provideLines
永远不会处于被赋予ctrl+c的位置

为了证明这一点,打开cmd并键入带有程序参数的程序(在我的例子中,我使用
ant
)。如果键入
ant
,然后按ctrl+c,光标将移动到新行

有两种方法可以控制终止行为:

  • 您可以使用(从中找到的)。这样做将允许您处理发生的事情(可能是问题)
  • 或者您可以创建自己的终止参数,如
    -q
    q
    ,这将触发结束程序的操作(可能是
    系统退出(1)
    )。这样,您可以模拟该输入

  • 尝试将此作为评论,但读起来不正确。但这并不完全是一个“答案”

    所以Java在控制台输入方面非常糟糕。它一次读取一整行,而您对此无能为力——在用户点击return之前,无法捕获特殊字符,甚至无法看到任何输入。此外,我认为ctrl-d将关闭您的输入会话--(如果您不在此处使用任何其他建议,请将该测试添加到您的用例中,因为它会使您进入一种出乎意料的状态!)

    三项建议:

    最简单的方法:如果您可以使用GUI,并且没有真正寻找正在进行的输入/响应REPL,那么最简单的方法通常是使用JOptionPane弹出一个快速对话框。这是一个获得一些用户输入的单行解决方案,但对于正在进行的命令驱动系统来说并不太好

    如果您不能使用swing(如果您运行的是headless),那么您可能没有什么选择,但是您可以使用JLine库。这将给你更多的灵活性。Groovysh就是这样做的,它是REPL。它可以让你看到输入的每个字符,并完成一些操作,比如用户可以键入文件名的一部分,然后点击tab键,然后你为他输入其余的字符

    如果您不想使用JLine,但想要REPL的感觉,还有一个更复杂的GUI解决方案——创建一个swing控制台窗口。一个简单的解决方案就是一个文本输入框,允许键入内容和一个文本区域来显示结果,但肯定有一些库提供了更完整的控制台解决方案


    这里的要点是,仅使用Java标准输入并不是一个很好的解决方案,除了一个简单的/个人的脚本之外——即使这样,我也避免使用它。可能不是您要求的答案,但可能是您需要的答案:)

    在UNIX/Linux中,当您键入
    CTRL-C
    时,shell会截获它并向进程发送一个
    SIGINT
    信号——请参阅:

    因此,系统规则项目没有任何帮助——在这种情况下,进程不会收到任何字符输入

    默认情况下,整个JVM在接收到
    SIGINT
    时关闭。对于正在运行的测试来说,这显然是个坏消息

    这个所谓的问题可能有用

    Java可移植性的一个副作用是,对于某些操作系统功能,它要么将内容抽象出来,直到无法识别,要么根本不公开它们

    我怀疑你的要求无法实现

    如果允许您稍微更改需求,您可以要求用户使用
    CTRL-D
    ——这将使用
    EOF
    关闭stdin


    尽管这有点过分,但您可以使用
    ProcessBuilder
    启动一个全新的JVM来运行您的程序。您可能会想象得到一个API向该进程发送任意信号。但是出于可移植性的原因,您所能做的就是
    process.destroy()
    ,它发送
    SIGTERM

    当您按CTRL-C键时,操作系统会做什么取决于主机环境。你能告诉我们你在用什么操作系统吗?