Search code examples
javajunitpowermockpowermockito

How do I mock a private field using PowerMockito?


The solution proposed as a duplicate is not a PowerMockito solution and as a consequence does not answer this question. Further, this question IS answered legitimately below.

IDK if this is a duplicate or not but I sure can't find the item in question if it is. I keep expecting this to be really simple, since it is pretty simple with reflection but I'd rather do it using the right tools.

Clarification: Legacy code. No getters / setters.

Is it correct to use Whitebox for this? I thought it was "Off Limits" i.e. part of the internal API? ...or was that strictly Mockito?


Solution

  • See Whitebox.setInternalState(...).

    For example - given class A which needs to be tested:

    public class A {
        private B b;
    
        public A() {
            b = new B();
        }
    
        public void doSomething() {
            b.doSomething();
        }
    
    }
    

    which has a private instance of B:

    public class B {
    
        public void doSomething() {
            // some long running, resource intensive process...
            System.out.println("Real B.doSomething() was invoked.");
        }
    
    }
    

    then Whitebox can be used to set the private state of A so it can be tested:

    import static org.mockito.Mockito.doNothing;
    import static org.mockito.Mockito.verify;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.Mock;
    import org.mockito.runners.MockitoJUnitRunner;
    import org.powermock.reflect.Whitebox;
    
    @RunWith(MockitoJUnitRunner.class)
    public class ATest {
    
        @Mock
        private B b;
    
        private A a;
    
        @Before
        public void prepareTest() {
            doNothing().when(b).doSomething();
    
            a = new A();
            Whitebox.setInternalState(a, B.class, b);
        }
    
        @Test
        public void doSomething() {
            a.doSomething();
            verify(b).doSomething();
        }
    
    }