【问题标题】:Junit5 is unable to execute shell commands within testsJunit5 无法在测试中执行 shell 命令
【发布时间】:2021-12-22 10:44:00
【问题描述】:

我对使用 Junit 5 运行脚本有疑问。我有以下代码:

public class RunMvnSubprocess {
    @Test
    public void main() throws IOException, InterruptedException {
        String[] cmd = new String[]{"mvn.cmd", "-version"}; // command to be executed on command prompt.
        Process p = Runtime.getRuntime().exec(cmd);
        try (BufferedReader output = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
            String line;
            while ((line = output.readLine()) != null) {
                System.out.println(line);
            }
        }
        p.waitFor();
    }
}

当我使用 Junit 5.7.0 运行它时,没有输出。但是,在 Junit 4.13.2 上运行它可以正常工作。

请注意,我在 Windows 10 Pro 版本 21H1 中运行此测试。

编辑:

修改

new String[]{"mvn.cmd", "-version"}

new String[]{"cmd", "/c", "\"mvn -version\""}

对我有用,但启动子外壳是一种不好的做法,因此我将这种解决方法作为最后的手段。

【问题讨论】:

    标签: java junit junit4 junit5


    【解决方案1】:

    请注意,当调用 Windows 命令 CMD.EXE 来解释 mvn.cmd 的内容时,您正在隐式运行子 shell,因此您的 cmd 的值相当于:

    cmd = new String[]{ "cmd", "/c", "call mvn.cmd -version"};
    

    如果您没有收到来自waitFor 的错误代码或没有输出或没有异常,则该问题将在 STDERR 流中报告。改为使用 ProcessBuilder,您可以将 STDERR 合并到 STDOUT,如下所示:

    ProcessBuilder pb = new ProcessBuilder(cmd);
    // No STDERR => merge to STDOUT
    pb.redirectErrorStream(true);
    
    Process p = pb.start();
    

    另外,不需要编写太多代码来消耗 STDOUT:

    try(var stdo = p.getInputStream()) {
        stdo.transferTo(System.out);
    }
    
    int rc = p.waitFor();
    if (rc != 0) throw new RuntimeException("test failed");
    

    希望这能解释您使用 mvn 命令的问题。

    【讨论】:

    • 感谢@DuncG 的回答。我仍然没有得到任何输出,但是 rc 的值是 1 所以我得到了一个 RuntimeException 引发。
    • 所以我的子进程以非零代码退出(测试套件以0退出),我不知道为什么,因为没有消息。
    • 你已经像上面那样切换到 ProcessBuilder 了?您应该澄清“mvn.cmd”包含的内容,因为您的命令列表{"cmd", "/c", "\"mvn -version\""}:这意味着您的修复可以运行MVN.EXE或MVN.CMD,具体取决于当前目录的内容,以及环境变量@987654329 @ 和 PATHEXT 所以与第一个 cmd 不同。
    • 是的,我切换到上面的流程构建器并尝试使用mvn.exemvn.cmd。使用前者会引发 IOException,而与 {"mvn.cmd", "-version"}' 对应的子进程以代码 1 退出。我什至尝试在输入流上调用 read,它返回 -1,这意味着流中没有字节。
    猜你喜欢
    • 2020-05-19
    • 2021-05-08
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 2018-12-01
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    相关资源
    最近更新 更多