Saturday 1 September 2012

Test private methods using JUnit Framework

   Testing the private methods separately is very rare situation as usually we indirectly test the private methods by testing the public methods of the same class, as if private method is not getting called by any public method in the class then it is considered as dead code (unused code).
   So what is that exact situation in which we need separate testing of private methods. We divide the public methods which are too long or contains complex logic. And we migrate the code to separate private methods. And it is not a good idea to skip the unit testing of the private methods just because they are not accessible outside the class.
    But while testing the private methods using JUnit framework java security layer prevent us from accessing private methods and variables. But still there is a way we can test private methods that is by using Java Reflection API. Using Java Reflection API we can access the private variables and methods of the class.
    Consider the following class which we want to test.

package j2yogi.example;
public class Dummy {
 private String str = "This is the use of reflection.";
 private int getSquare(int a){
  return a*a;
 }
}

Now I want to test private "getSquare(int a)" method using Java Reflection in JUnit TestClass. And also I can access the private variable "str" in test class.

package j2yogi.test;

import j2yogi.example.Dummy;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import junit.framework.TestCase;

public class TestDummy extends TestCase{
 
 public void testPrivateVariables() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException{
  Dummy dummy = new Dummy();
  Field strfield = dummy.getClass().getDeclaredField("str");
  strfield.setAccessible(true);
  String string = String.valueOf(strfield.get(dummy));
  System.out.println(string);
  assertEquals("This is the use of reflection.", string);
 }
 
 public void testPrivateMethod() throws NumberFormatException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
  Dummy dummy = new Dummy();
   Method addMethod[] = dummy.getClass().getDeclaredMethods();
   addMethod[0].setAccessible(true);
   int res = Integer.parseInt((String.valueOf(addMethod[0].invoke(dummy, 2))));
   System.out.println("result: "+res);
   assertEquals(4, res);
 }
} 
 
How to run this code:-
Create the j2yogi.example package then create the Dummy class and copy Dummy class 
code from above snippet. 
Then create j2yogi.test package and create TestDummy  class and copy the TestDummy class 
code from above snippet. Now code is ready but we need JUnit dependency for execution of 
this code. SO download JUnit dependency and add it to class path. 
Now you can run the test case by running TestDummy class :).
 

This is just a small benefit of freedom provided by Java Reflections API. Similarly you can also test the protected methods. You can also check simple introduction to Java Reflections.
If you want to learn JUnit in detail i found this site very helpful. click here to learn JUnit.