PowerMock : How to test a private method

on

“I HAVE THE POWER!!” – I had this feeling a few days ago. I will be honest that at work I do not get time to write unit test cases for each and every piece of code that I write. Often when I do have time, I make an effort to write test cases even for the trivial piece of code blocks such as — Check if properties file is present.

I was working on new code where I had the luxury to write the code in peace (a rarity at my work place where every project is like a fire drill). While writing test cases I came across a situation where I had a class with two methods:

<pre>public void my_public_method()

private void my_private_method()

 

I wanted to write test cases for both the method. However Junit would not allow me to write a test case for a private method. I searched over internet forums and every one suggested that I use Java Reflection API  to write my test cases or make my private method public, which I did not want to do.

That’s when POWERMOCK steps in and in a tiny little section of its documentation I noticed a piece of “WhiteboxImpl”  class which can help me test private methods.

So that’s what I am going to demonstrate in this tutorial.

STEP 1: Add Maven jar files

<properties>
    <relative.path>relative/svn/path</relative.path>
      <powermock.version>1.6.2</powermock.version>
  </properties>
 <dependencies>
........
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.powermock</groupId>
          <artifactId>powermock-module-junit4</artifactId>
          <version>${powermock.version}</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.powermock</groupId>
          <artifactId>powermock-api-easymock</artifactId>
          <version>${powermock.version}</version>
          <scope>test</scope>
      </dependency>
 <dependencies>

STEP 2: Create a class MyClass.java

 

</pre>
<pre>public class MyClass {
    //PUBLIC METHOD
    public String my_public_method(){
        String msg="This is my PUBLIC method";
        System.out.println(msg);
        return msg;
    }

    //PRIVATE METHOD
    private String my_private_method(){
        String msg="This is my PRIVATE method";
        System.out.println(msg);
        return msg;
    }
}

STEP 3: Write a test case for public method : my_public_method


import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.internal.WhiteboxImpl;

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class MyClassTest {
    final String publicMsg = "This is my PUBLIC method";
    final String privateMsg = "This is my PRIVATE method";

    @Test
    public void testMy_public_method() throws Exception {
        MyClass myClass = new MyClass();
        String msg=myClass.my_public_method();
        Assert.assertEquals(publicMsg,msg);
    }
}

As you can see above that there is no issue with calling a public method and it will run successfully but when you try and call the private method, the code will show error that private method is not visible.

STEP 4: Use PowerMock’s WhiteboxImpl class to test a private method.

Before you do anything you need to make sure that you added Powermock annotations correctly.

  • Add these two annotations to your class.

@RunWith(PowerMockRunner.class)

@PrepareForTest(MyClass.class)

  • Write the code to test private method.
    @Test
    public void testMy_private_method() throws Exception {
        MyClass myClass = new MyClass();
        String msg= WhiteboxImpl.invokeMethod(myClass, "my_private_method");
        Assert.assertEquals(privateMsg,msg);
    }

The syntax is pretty simple WhiteboxImpl.invokeMethod(<class object>, “<Name of the private Method>,input param1, input param2,…);

The WhiteBoxImpl class actually uses “Java Reflection API” in the background to make a call, but for the lazy coders like me, who do not want to write Reflection API(Read hate Reflection API), the WhiteBoxImpl class is a small piece of coding heaven.

Now run the test class and you will see that test cases have passed.

~Ciao –Repeat the mantra – “I HAVE THE POWER{MOCK}!!!”