4

Dear stackoverflow comrades, I again have a problem in getting a specific PowerMock / Mockito case to work. The issue is, that I need to verify the call of a private static method, which is called from a public non-static method. A similar example I posted previously on How to suppress and verify private static method calls?

This is my code:

class Factory {

        public String factorObject() throws Exception {
            String s = "Hello Mary Lou";
            checkString(s);
            return s;
        }

        private static void checkString(String s) throws Exception {
            throw new Exception();
        }
    }

And this is my testclass:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Factory.class)
public class Tests extends TestCase {

    public void testFactory() throws Exception {

        Factory factory = mock(Factory.class);
        suppress(method(Factory.class, "checkString", String.class));
        String s = factory.factorObject();
        verifyPrivate(factory, times(8000)).invoke("checkString", anyString());
    }
}

The problem here is, that the Test is successful, but it shouldn't be. It shouldn't be because the private static method should be called exactly 1 times. But no matter what value I put in times(), it always verifies it as true... halp :(

Community
  • 1
  • 1
Malvin
  • 859
  • 2
  • 11
  • 19
  • 1
    You shouldn't really be testing `private` methods. This closely couples your unit tests to the implementation which results in _pain_. Why not check that the `class` throws an `Exception` when it's supposed to? – Boris the Spider May 13 '13 at 06:22
  • Basically you are right, but unfortunately in my *real* project the condition how and when the exception is thrown is hidden in closed code. That's why I am going for the suppress behavior. I just need to verify the call to it. – Malvin May 13 '13 at 06:42
  • 1
    This already answered in http://stackoverflow.com/questions/14065515/mockito-bypass-static-method-for-testing – Rudy May 13 '13 at 06:44

1 Answers1

13

Ok, I think I found the answer, but it was a headache. Rudy gave me the final hint with using using a spy, but it was still not trivial (although the solution looks "baby-easy"). Here is the complete solution:

import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
import static org.powermock.api.mockito.PowerMockito.doNothing;
import static org.powermock.api.mockito.PowerMockito.spy;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Factory.class)
public class Tests extends TestCase {

    public void testFactory() throws Exception {

        Factory factorySpy = spy(new Factory());
        String s = factorySpy.factorObject();
        doNothing().when(factorySpy, "checkString", anyString());
        verifyPrivate(factorySpy, times(1)).invoke("checkString", anyString()); 
    }
}
Malvin
  • 859
  • 2
  • 11
  • 19
  • Late to the game, but you can also keep it static by doing mockStatic(Factory.class); then doNothing().when(Factory.class, "checkString", anyString()); Then you don't need to create the spy instance – Victor Grazi Nov 23 '16 at 16:26
  • Hi Victor Grazi i can't figure how i verify private static method is called in a public static method. What should i write instead of verifyPrivate(factorySpy, times(1)).invoke("checkString", anyString()); To make it work with mockStatic ? – Nolyurn Nov 29 '18 at 13:59