Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to go around Runtime.getRuntime() while writing JUnit?

I have a class where Runtime.getRuntime() is used for executing a script from command line and getting the result for further processing.

But when I write JUnit for this class, I cannot find a way to mock/avoid this Runtime.getRuntime().exec() .

I cannot use EasyMock or PowerMock or any other mock api other than Mockito.

Please give me a way to overcome this problem, because this is affecting the code coverage.

like image 443
unni Avatar asked Jun 01 '12 08:06

unni


People also ask

What is runtime getRuntime exec in Java?

Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime method.

How do you do a mock runtime?

getRuntime(). exec() you could "mock" the script/program/etc. it's supposed to be calling. Instead of passing the real command-line string into exec() , write a test script and execute it instead.


2 Answers

You must refactor. Extract Runtime.getRuntime().exec() into a separate class:

public class Shell {

  public Process exec(String command) {
    return Runtime.getRuntime().exec(command);
  }

}

Now insted of calling getRuntime() explicitly inject Shell class somehow to your class under test:

public class Foo {

  private final Shell shell;

  public Foo(Shell shell) {
    this.shell = shell;
  }

  //...
  shell.exec(...)

}

In JUnit test simply inject mocked Shell class by passing it to constructor:

@Mock
private Shell shellMock;

new Foo(shellMock);

Sidenote: yes, I am not creating a Shell interface with one implementation. Do you mind? Mockito is not. Bonus: you can now verify if the correct process was called:

verify(shellMock).exec("/usr/bin/gimp");
like image 78
Tomasz Nurkiewicz Avatar answered Oct 10 '22 02:10

Tomasz Nurkiewicz


Tomasz Nurkiewicz has provided a wonderful answer. But there is an alternative.

You can move Runtime.getRuntime() into its own method in the class that you're testing; then test it with a Mockito spy. In the Mockito spy, you can override this particular method with a version that creates a mock Runtime, then do whatever you like with it.

However, Tomasz's approach is cleaner, and I recommend it thoroughly. I just wanted to say that there IS another way to do it, without resorting to Powermock.

like image 30
Dawood ibn Kareem Avatar answered Oct 10 '22 02:10

Dawood ibn Kareem