mhshams
mhshams

Reputation: 16972

Java - Unit Test

Given this method in a Java class:

public void execute(String command) {

    ProcessBuilder processBuilder = new ProcessBuilder(command);
    Process process = processBuilder.start();

    int exitValue = process.waitFor();
    if (exitValue != 0) {
        throw new RuntimeException("a message here...");
    }
}

I'm trying to come up with a proper cross platform unit test for this method.

I'm looking for a common command across all operating systems (Win, Linux, Mac and ...) or a fake command that I can pass to this method in my unit tests.

Any suggestion ?

Upvotes: 5

Views: 3327

Answers (2)

gontard
gontard

Reputation: 29530

This method can't be tested via a unit test but only via an integration test. To make a unit test you could do a small refactor. Introduce a new interface ProcessBuilderFactory (and a default implementation) and inject it on your class.

public interface ProcessBuilderFactory {
    ProcessBuilder createProcessBuilder(String command);
}

public class DefaultProcessBuilderFactory implements ProcessBuilderFactory {
    public ProcessBuilder createProcessBuilder(String command) {
        return new ProcessBuilder(command);
    }
}

public class ProcessExecutor {
    private ProcessBuilderFactory processBuilderFactory;
    private ProcessExecutor(ProcessBuilderFactory processBuilderFactory) {
        this.processBuilderFactory = processBuilderFactory;
    }

    public void execute(String command) {
        ProcessBuilder processBuilder = processBuilderFactory.createProcessBuilder(command);
        Process process = processBuilder.start();

        int exitValue = process.waitFor();
        if (exitValue != 0) {
            throw new RuntimeException("a message here...");
        }
    }
}

and then you could make a unit test by injecting a mock ProcessBuilderFactory. You start writing the test, you create a mock ProcessBuilderFactory, returning a mock ProcessBuilder... damned, ProcessBuilder is final too :(

A strong reminder : write the test first !

So we have two options :

  1. introduce a new interface for wrapping the ProcessBuilder with a default implementation... in the same way we create the ProcessBuilderFactory
  2. undo the refactoring and look at PowerMock, for final class mocking

Upvotes: 8

Jayan
Jayan

Reputation: 18458

Since this is java unit test you could use java.exe as standard exe. Say java.exe -version. It will always be there :). Use current jdk from java.home and then use that to refer java.exe

Looking at specific requirement could you use any mocking framework? (jmockit for example)

Upvotes: 2

Related Questions