Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 363
mhshams Avatar asked Aug 27 '12 07:08

mhshams


1 Answers

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
like image 177
gontard Avatar answered Oct 02 '22 21:10

gontard