How to Unit test private methods in Java and Kotlin

GOVIND DIXIT
MindOrks
Published in
4 min readJul 23, 2019

Yes, This is a million-dollar question. How to unit test private methods?

Should a developer test the private methods in his codebase? or leaving them on the trust of public methods is a way. Every developer has its own opinion that whether should we actually test them or not. So, In a nutshell, the question got reduced to is “Is there exists any good approach we can try for this Job?”

So, here are all the possible options available to a developer to test private methods of his Java / kotlin based Apps in 2019:

  1. Don’t test private methods 😜(No roots, no sour grapes)
  2. Give the methods public access 😒 (No, I won’t do this it’s against coding practices. I am a good developer, I follow best practices)
  3. Use a nested test class 😒 (This is not good to mixed production code with test code. Do I need to mention again that I am a good developer and I follow only best practices)
  4. Use Java Reflection 😃(Yes, this seems interesting I’m in for it)

Despite the common belief it is actually possible to access private fields and methods of other classes via Java Reflection. It is not even that difficult. This can be very handy during unit testing.

Note: This only works when running the code as a standalone Java application, as you do with unit tests and regular applications. If you try to do this inside a Java Applet, you will need to fiddle around with the SecurityManager. But, since that is not something you need to do very often, it is left out of this text so far.

Method Parameter Reflection support was added in Java 8. Simply put, it provides support for getting the names of parameters at runtime.

Accessing Private Fields

To access a private field you will need to call the Class.getDeclaredField(String name) or Class.getDeclaredFields() method. The methods Class.getField(String name) and Class.getFields() methods only return public fields, so they won't work. Here is a simple example of a class with a private field, and below that the code to access that field via Java Reflection:

public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {
this.privateString = privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");
privateStringField.setAccessible(true);String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);

This code example will print out the text “fieldValue = The Private Value”, which is the value of the private field privateString of the PrivateObject the instance created at the beginning of the code sample.

Notice the use of the method PrivateObject.class.getDeclaredField("privateString"). It is this method call that returns the private field. This method only returns fields declared in that particular class, not fields declared in any superclasses.

Notice the line in bold too. By calling Field.setAcessible(true) you turn off the access checks for this particular Field instance, for reflection only. Now you can access it even if it is private, protected or package scope, even if the caller is not part of those scopes. You still can't access the field using the normal code. The compiler won't allow it.

Accessing Private Methods

To access a private method you will need to call the Class.getDeclaredMethod(String name, Class[] parameterTypes) or Class.getDeclaredMethods() method. The methods Class.getMethod(String name, Class[] parameterTypes) and Class.getMethods() methods only return public methods, so they won't work.

Here is a simple example of a class with a private method, and below that the code to access that method via Java Reflection:

public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {
this.privateString = privateString;
}
private String getPrivateString(){
return this.privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");Method privateStringMethod = PrivateObject.class.
getDeclaredMethod("getPrivateString", null);
privateStringMethod.setAccessible(true);String returnValue = (String)
privateStringMethod.invoke(privateObject, null);
System.out.println("returnValue = " + returnValue);

This code example will print out the text “returnValue = The Private Value”, which is the value returned by the method getPrivateString() when invoked on the PrivateObject the instance created at the beginning of the code sample.

Notice the use of the method PrivateObject.class.getDeclaredMethod("privateString"). It is this method call that returns the private method. This method only returns methods declared in that particular class, not methods declared in any superclasses.

Notice the line in bold too. By calling Method.setAcessible(true) you turn off the access checks for this particular Method instance, for reflection only. Now you can access it even if it is private, protected or package scope, even if the caller is not part of those scopes. You still can't access the method using the normal code. The compiler won't allow it.

Let’s try this knowledge to some production-level code.
Here is the class containing some private methods which we want to test.

LoginPresenter.kt

Let’s test the private function saveAccountof loginPresenter

LoginPresenterTest.kt

Thanks for reading! If you enjoyed this story, please click the 👏 button and share to help others find it!

Feel free to leave a comment 💬 below.

Have feedback?

Let’s connect on Twitter, LinkedIn, Quora

--

--

GOVIND DIXIT
MindOrks

Building @CRED_Club • Ex @UrbanCompany_UC @Headout @RocketChat • Google Summer of Code 20 & 19 • Mentor @GSoC @Google CodeIn • Facebook Deep Learning Scholar🏅