Search code examples
unit-testingjunitmockitopowermockpowermockito

powermockito spy private void method invocation


For a test class with a private void method, what is the right way to mock the behaviour of the method. The solution below invokes the method instead.

public class TestWizard {

    private void testOne(){
        throw new NullPointerException();
    }

    private void testTwo(){
        testOne();
    }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest({TestWizard.class})
public class WTest {
    @Test
    public void testWizard() throws Exception {

        TestWizard wizard2 = Whitebox.newInstance(TestWizard.class);
        TestWizard wizard = Mockito.spy(wizard2);
        PowerMockito.doNothing().when(wizard, "testTwo");

    }
}

The error is:

java.lang.NullPointerException
    at tuk.pos.wizard.model.TestWizard.testOne(TestWizard.java:6)
    at tuk.pos.wizard.model.TestWizard.testTwo(TestWizard.java:10)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:1862)
    at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:824)
    at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:689)
    at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401)
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:105)

Solution

  • Use PowerMockito.spy(...) instead of Mockito.spy(...).

    Tested with PowerMockito 2.0.5

    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;
    import org.powermock.reflect.Whitebox;
    
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(WTest.TestWizard.class)
    public class WTest {
    
        public class TestWizard {
    
            private void testOne(){
                throw new NullPointerException();
            }
    
            private void testTwo(){
                testOne();
            }
        }
    
        @Test
        public void testWizard() throws Exception {
    
            TestWizard spy = PowerMockito.spy(Whitebox.newInstance(TestWizard.class));
            PowerMockito.doNothing().when(spy, "testTwo");
    
            spy.testTwo();
        }
    }
    

    Try to restrict the usage of spies to legacy code. In most other cases a refactoring should be the preferred solution.