Search code examples
javatestingjunitmockitopowermock

How to mock private method for testing using PowerMock?


I have a class which I would like to test with a public method that calls private one. I'd like to assume that private method works correctly. For example, I'd like something like doReturn....when.... I found that there is possible solution using PowerMock, but this solution doesn't work for me. How It can be done? Did anybody have this problem?


Solution

  • I don't see a problem here. With the following code using the Mockito API, I managed to do just that :

    public class CodeWithPrivateMethod {
    
        public void meaningfulPublicApi() {
            if (doTheGamble("Whatever", 1 << 3)) {
                throw new RuntimeException("boom");
            }
        }
    
        private boolean doTheGamble(String whatever, int binary) {
            Random random = new Random(System.nanoTime());
            boolean gamble = random.nextBoolean();
            return gamble;
        }
    }
    

    And here's the JUnit test :

    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 static org.mockito.Matchers.anyInt;
    import static org.mockito.Matchers.anyString;
    import static org.powermock.api.mockito.PowerMockito.when;
    import static org.powermock.api.support.membermodification.MemberMatcher.method;
    
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(CodeWithPrivateMethod.class)
    public class CodeWithPrivateMethodTest {
    
        @Test(expected = RuntimeException.class)
        public void when_gambling_is_true_then_always_explode() throws Exception {
            CodeWithPrivateMethod spy = PowerMockito.spy(new CodeWithPrivateMethod());
    
            when(spy, method(CodeWithPrivateMethod.class, "doTheGamble", String.class, int.class))
                    .withArguments(anyString(), anyInt())
                    .thenReturn(true);
    
            spy.meaningfulPublicApi();
        }
    }