PowerMockito.whenNew()

There are some cases where source code directly create a new instance of object without any injection mechanism. JVM will create an instance with actual class with actual methods. For these cases, we can use PowerMockito.whenNew() method to

Similar to Mockito's when() statement, we can tell PowerMock to inject our mock instead of creating new instance of real object.

Here is an example:

// Example Source Class
public class ExampleClass {
    public int getHeight() {
        // Lets say we have a generic method which provides different result base on the provided id
        final CustomClass customClassInstance = new CustomClass();
        return customClass.getHeight();
    }
}

In above example, CustomClass instance is created without any mechanism to inject it, lets see how can we tell PowerMockito to inject our mock.

@RunWith(PowerMockRunner.class)
@PrepareForTest({
    ExampleClass.class
})
public class ExampleClassTest {

    private ExampleClass classUnderTest;

    @Before
    public void setUp() throws Exception {
        // Create constructor of ExampleClass
        classUnderTest = new ExampleClass();
    }

    @Test
    public void getHeight_shoudReturnHeightOfView() throws NoSuchMethodException {
        final int expectedHeight = 100;
        // Given
        final CustomClass mckCustomClass = Mockito.mock(CustomClass.class);
        Mockito.when(mckCustomClass.getHeight()).theReturn(expectedHeight);
        // Make sure you match exact parameters while mocking (same as we do for Mockito.mock statements).
        // There is also withArguments(first, second, ....)
        // and withAnyArguments() for cases when you don't care for arguments passed.
        PowerMockito.whenNew(CustomClass.class).withNoArguments().thenReturn(mckCustomClass);

        final int actualResult = classUnderTest.getHeight();

        Assert.assertEquals(expectedHeight, actualResult);
    }
}

Note: keep in mind, if you need to manipulate behavior (byte code) of any class, as we are doing in case of whenNew() method, we need to add ExampleClass.class in @PrepareForTest.

Note Keep in mind, whenNew() will not work when new instance was created inside a nested scope.

Last updated