I have a class that in some of its methods is using
Runtime.getRuntime().exec ...
For example:
public class MyClass {
public void doSomething() {
...do something...
Runtime.getRuntime().exec ...
...do something else
}
}
Unfortunately I "cannot refactor" the class due to some requirements. I want to create jUnit tests on this class and I'm finding it hard to mock the Runtime class.
Let's say I want to test the "doSomething" method in the cases where Runtime process returns the X result or the Y result. Is there any way to mock it?
You can do that using PowerMockito
and mockStatic
method.
The idea is to mock the static Runtime.getRuntime()
method to return a mocked runtime object, and on that you can control the outcome of exec()
@RunWith(PowerMockRunner.class)
@PrepareForTest(Runtime.class)
public class TestClass {
@Mock private Runtime mockRuntime;
@Test
public void test() {
PowerMockito.mockStatic(Runtime.class);
when(Runtime.getRuntime()).thenReturn(mockRuntime);
when(mockRuntime.exec()).thenReturn("whatever you want");
// do the rest of your test
}
}
A working example :
In src/main/java/sandbox/xx, XX.java
package sandbox.xx;
import java.io.File;
import java.io.IOException;
class XX {
Process run(final String command) throws IOException {
return this.run(command, null, null);
}
Process run(final String command, final String[] envp) throws IOException {
return this.run(command, envp, null);
}
Process run(final String command, final String[] envp, final File dir) throws IOException {
return Runtime.getRuntime().exec(command, envp, dir);
}
Process run(final String[] cmdarray) throws IOException {
return this.run(cmdarray, null, null);
}
Process run(final String[] cmdarray, final String[] envp) throws IOException {
return this.run(cmdarray, envp, null);
}
Process run(final String[] cmdarray, final String[] envp, final File dir) throws IOException {
return Runtime.getRuntime().exec(cmdarray, envp, dir);
}
}
In src/test/java/sandbox/xx, XXTest.java
package sandbox.xx;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(XX.class) // watch it: not @PrepareForTest(Runtime.class)!
public class XXTest {
private static final String TRIGGER_ARG = "some arg";
private static final String EXPECTED_PREFIX = "gotcha!";
private static final String COLON = ": ";
private static final String EXPECTED_RESULT = EXPECTED_PREFIX + COLON + TRIGGER_ARG;
@Test
public void test() throws IOException {
final Runtime mockRuntime = PowerMockito.mock(Runtime.class);
PowerMockito.mockStatic(Runtime.class);
Mockito.when(Runtime.getRuntime()).thenReturn(mockRuntime);
Mockito.when(mockRuntime.exec(ArgumentMatchers.eq(TRIGGER_ARG), ArgumentMatchers.any(), ArgumentMatchers.any())).thenAnswer(invocation -> {
final Process mockProcess = PowerMockito.mock(Process.class);
Mockito.when(mockProcess.toString()).thenReturn(EXPECTED_PREFIX + COLON + invocation.getArguments()[0]);
return mockProcess;
});
final XX xx = new XX();
Assert.assertEquals(EXPECTED_RESULT, xx.run(TRIGGER_ARG).toString());
Assert.assertNull(xx.run("some other arg"));
}
}
Hope this helps
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With