Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock java.lang.Runtime with PowerMockito

want to write an unittest for a method like

public static void startProgram() {
    process = Runtime.getRuntime().exec(command, null, file);
}

I don't want to inject the runtime object for some reasons, so I wanted to stub the getRuntime method that it returns a Runtime mock... I tried it this way:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Runtime.class)
public class ProgramTest {

    @Test
    public void testStartProgram() {
        Runtime mockedRuntime = PowerMockito.mock(Runtime.class);

        PowerMockito.mockStatic(Runtime.class);
        Mockito.when(Runtime.getRuntime()).thenReturn(mockedRuntime);

        ... //test
    }
}

But this doesn't work. Actually nothing seems to be mocked. In the test the normal Runtime object is used.

Anyone any idea why this doesn't work and/or how it works?

As this mini example seems not to reproduce the problem here is the full test code: method to test (shortened)

public static synchronized long startProgram(String workspace) {
    // Here happens someting with Settings which is mocked properly
    File file = new File(workspace);
    try {
        process = Runtime.getRuntime().exec(command, null, file);
    } catch (IOException e) {
        throw e;
    }
    return 0L;
}

and the test:

@Test
public void testStartProgram() {
    PowerMockito.mockStatic(Settings.class);
    Mockito.when(Settings.get("timeout")).thenReturn("42");

    Runtime mockedRuntime = Mockito.mock(Runtime.class);
    // Runtime mockedRuntime = PowerMockito.mock(Runtime.class); - no difference
    Process mockedProcess = Mockito.mock(Process.class);

    Mockito.when(mockedRuntime.exec(Mockito.any(String[].class), Mockito.any(String[].class),
                    Mockito.any(File.class))).thenReturn(mockedProcess);

    PowerMockito.mockStatic(Runtime.class);
    Mockito.when(Runtime.getRuntime()).thenReturn(mockedRuntime);

    startProgram("doesnt matter");
}

Then, in the test, the call to Runtime.getRuntime() doesn't bring the mock and that's why an IOException is thrown because the String is no directory...

like image 620
Jogi Avatar asked Jun 04 '14 13:06

Jogi


People also ask

How to create an example using powermock with Mockito?

To create an example using PowerMock, we need to go through the following steps. Step 1: Add the following PowerMock dependencies in pom.xml file. To use PowerMock with Mockito, we need to apply the following two annotations in the test: @RunWith (PowerMockRunner.class): It is the same as we have used in our previous examples.

What is powermockito in Java?

The PowerMockito provides the functionality to work with the Java reflection API. Let's understand the concept of PowerMock with the help of an example. Here, we are going to create an example of PowerMock with Mockito and JUnit frameworks.

What is the powermock framework?

Overview. This is where the PowerMock framework comes into play. PowerMockito is a PowerMock’s extension API to support Mockito. It provides capabilities to work with the Java Reflection API in a simple way to overcome the problems of Mockito, such as the lack of ability to mock final, static or private methods.

What is the use of @Mock annotation in Java?

We use the annotation @Mock on the class instance which we need to test and we test various conditions using the Mockito methods like verify (),when (), doThrow () etc. While Mockito can help with test case writing, there are certain things it cannot do like mocking or testing private, final or static methods.


1 Answers

My bad in the comments, apologies, I had an inner class for the test and that's why I had no trouble. I then realized this and saw your @PrepareForTest(Runtime.class) which should read @PrepareForTest(MyClass.class) (replace MyClass with whatever name you have) because Runtime is a system class. You can read more about this here and find more examples here.

like image 198
Morfic Avatar answered Sep 20 '22 13:09

Morfic