Sunday, March 6, 2011

Testing private methods in Java

In a perfect world you shouldn't need to test private methods in Java. If you are doing greenfield and you have committed to Test Driven Development, the unit test you write for your public and protected methods should be robust enough to cover the private methods as well. Legacy code is a different animal. Having to deal with spaghetti code, combined with a fast approaching deadline and the risk and effort in completely refactoring the whole thing, justifies the use of an utility for testing private methods...in my humble opinion that is. Here is one I have used plus an example:

import java.lang.reflect.Method;

public class PrivateMethodTestingUtil {
   
    public static Object invokePrivateMethod(Object objectWithPrivateMethod, String methodName, Class[] classArgs , Object[] objectArgs) throws Exception {   
       
        Method privateMethod = objectWithPrivateMethod.getClass().getDeclaredMethod(methodName, classArgs);
       
        privateMethod.setAccessible(true);   
       
        return privateMethod.invoke(objectWithPrivateMethod, objectArgs);
    }
   
}



example


    @Test
    public void ensureValidatePasswordReturnsTrue() throws Exception{
        

      User user = new User();
      user.setPassword("password");
      user.setConfirmPassword("password");

     String someStringForASecondArg = "secondArg";

      boolean validate = PrivateMethodTestingUtil.invokePrivateMethod(validator,
            "validatePassword", new Class[]{User.class, String.class},
                new Object[]{user, someStringForASecondArg});


        assertTrue(validate);
       
    }



public class Validator {

    public boolean validate(User user) {

          return validatePassword(User, "hello");
    }

    private boolean validatePassword(User user, String secondArg) {

        return true;
    }
}