How to bypass Runtime.getRuntime () when writing JUnit?

I have a class where Runtime.getRuntime () is used to execute a script from the command line and get 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 api layouts other than Mockito .

Please give me a way to overcome this problem because it affects code coverage.

+6
source share
3 answers

You have to reorganize. Extract Runtime.getRuntime().exec() into a separate class:

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

Now, when you call getRuntime() , we explicitly add the Shell class somehow to your tested class:

 public class Foo { private final Shell shell; public Foo(Shell shell) { this.shell = shell; } //... shell.exec(...) } 

In a JUnit test, just inject a cool Shell class by passing it to the constructor:

 @Mock private Shell shellMock; new Foo(shellMock); 

Sidenote: yes, I'm not creating a Shell interface with one implementation. Do not you mind? Mokito - no. Bonus: now you can check if the correct process has been called:

 verify(shellMock).exec("/usr/bin/gimp"); 
+13
source

Tomash Nurkevich gave a wonderful answer. But there is an alternative.

You can move Runtime.getRuntime() to your own method in the class that you are testing; then check it out by Mockito spies. In Mockito spies, you can override this particular method with the version that creates the Runtime layout, and then do whatever you like with it.

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

+3
source

I used sub-classification and redefinition (as explained in Michael C. Pers's book, Effective Work with Deprecated Code)

Suppose we have the following code:

 public class CannotChange{ public CannotChange(){} public void TryingToTest() throws IOException { ... Process proc = Runtime.getRuntime().exec("command"); ... } } 

Extract the runtime code in a protected method:

  public void TryingToTest() throws IOException { ... Process proc = execute("command"); ... } protected Process execute(string command){ return Runtime.getRuntime().exec(command); } 

Then in the test class, create a class that extends the CannotChange class and overrides execution

 public class CannotChangeTest{ private class CannotChangeForTesting extends CannotChange{ public CannotChangeForTesting(){ super(); } @Override public Process execute(String command){ return null; //or a mocked object } } @Test public void TestMethod(){ CannotChange cannotChange = new ForTestCannotChange(); cannotChange.TryingToTest(); } } 
0
source

Source: https://habr.com/ru/post/917157/


All Articles