Testing Private method using mockito

public class A {

    public void method(boolean b){
          if (b == true)
               method1();
          else
               method2();
    }

    private void method1() {}
    private void method2() {}
}

public class TestA {

    @Test
    public void testMethod() {
      A a = mock(A.class);
      a.method(true);
      //how to test like    verify(a).method1();
    }
}

How to test private method is called or not, and how to test private method using mockito?


Not possible through mockito. From their wiki

Why Mockito doesn't mock private methods?

Firstly, we are not dogmatic about mocking private methods. We just don't care about private methods because from the standpoint of testing private methods don't exist. Here are a couple of reasons Mockito doesn't mock private methods:

It requires hacking of classloaders that is never bullet proof and it changes the api (you must use custom test runner, annotate the class, etc.).

It is very easy to work around - just change the visibility of method from private to package-protected (or protected).

It requires me to spend time implementing & maintaining it. And it does not make sense given point #2 and a fact that it is already implemented in different tool (powermock).

Finally... Mocking private methods is a hint that there is something wrong with OO understanding. In OO you want objects (or roles) to collaborate, not methods. Forget about pascal & procedural code. Think in objects.


You can't do that with Mockito but you can use Powermock to extend Mockito and mock private methods. Powermock supports Mockito. Here's an example.


Here is a small example how to do it with powermock

public class Hello {
    private Hello obj;
    private Integer method1(Long id) {
        return id + 10;
    }
} 

To test method1 use code:

Hello testObj = new Hello();
Integer result = Whitebox.invokeMethod(testObj, "method1", new Long(10L));

To set private object obj use this:

Hello testObj = new Hello();
Hello newObject = new Hello();
Whitebox.setInternalState(testObj, "obj", newObject);

While Mockito doesn't provide that capability, you can achieve the same result using Mockito + the JUnit ReflectionUtils class or the Spring ReflectionTestUtils class. Please see an example below taken from here explaining how to invoke a private method:

ReflectionTestUtils.invokeMethod(student, "saveOrUpdate", "From Unit test");

Complete examples with ReflectionTestUtils and Mockito can be found in the book Mockito for Spring


Think about this in terms of behaviour, not in terms of what methods there are. The method called method has a particular behaviour if b is true. It has different behaviour if b is false. This means you should write two different tests for method; one for each case. So instead of having three method-oriented tests (one for method, one for method1, one for method2, you have two behaviour-oriented tests.

Related to this (I suggested this in another SO thread recently, and got called a four-letter word as a result, so feel free to take this with a grain of salt); I find it helpful to choose test names that reflect the behaviour that I'm testing, rather than the name of the method. So don't call your tests testMethod(), testMethod1(), testMethod2() and so forth. I like names like calculatedPriceIsBasePricePlusTax() or taxIsExcludedWhenExcludeIsTrue() that indicate what behaviour I'm testing; then within each test method, test only the indicated behaviour. Most such behaviours will involve just one call to a public method, but may involve many calls to private methods.

Hope this helps.