Junit5 is unable to execute shell commands within tests

Viewed 107

I had question about running scripts using Junit 5. I have the following piece of code:

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

I get no output when I run it using Junit 5.7.0. However, running this on Junit 4.13.2 works fine.

Please note that I am running this piece of test in Windows 10 Pro version 21H1.

EDIT:

Modifying

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

to

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

works for me, but launching a subshell is a bad practice so I am keeping this workaround as a last resort.

1 Answers

Note that you are implicity running a sub-shell as the Windows command CMD.EXE is called to interpret the contents of mvn.cmd, so your value of cmd is equivalent to:

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

If you get no error code from waitFor or no output or no exception, then the issue will be reported in the STDERR stream. Change to use ProcessBuilder instead and you can merge STDERR to STDOUT as follows:

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

Process p = pb.start();

Also, no need to write much code to consume STDOUT:

try(var stdo = p.getInputStream()) {
    stdo.transferTo(System.out);
}

int rc = p.waitFor();
if (rc != 0) throw new RuntimeException("test failed");

Hopefully this will explain your problem with the mvn command.

Related