• Private method is a which can be invoked by code in the same class. It is not inherited by subclasses.
  • A field is a class, interface, or enum with an associated value.
  • Methods in the java.lang.reflect.Field class can retrieve information about the field, such as its name, type, modifiers, and annotations.
  • Java inner class or nested class is a class i.e. declared inside the class or interface. We use inner classes to logically group classes and interfaces in one place so that it can be more readable and maintainable. Additionally, it can access all the members of outer class including private data members and methods.

  • A legacy application, we are not allowed to change the visibility of our methods, the best way to test private methods is to use reflection.
  • Internally we’re using helpers to get/set private and private static variables as well as invoke private and private static methods.
  • The following patterns related to the private methods and fields. We can’t change private static final variables through reflection.
[pastacode lang=”java” manual=”Method%20method%20%3D%20targetClass.getDeclaredMethod(methodName%2C%20argClasses)%3B%0Amethod.setAccessible(true)%3B%0Areturn%20method.invoke(targetObject%2C%20argObjects)%3B%0A” message=”Java Code” highlight=”” provider=”manual”/] [ad type=”banner”]

And for fields:

[pastacode lang=”java” manual=”Field%20field%20%3D%20targetClass.getDeclaredField(fieldName)%3B%0Afield.setAccessible(true)%3B%0Afield.set(object%2C%20value)%3B%0A” message=”Java Code” highlight=”” provider=”manual”/]

Notes:

1. targetClass.getDeclaredMethod(methodName, argClasses) is looks like private methods. The same thing applies for getDeclaredField.
2. The setAccessible(true) is required.

Two examples of where we need to test a private method:

Decryption routines –

we would not want to make them visible to anyone to see just for the sake of testing, else anyone can use them to decrypt. But they are intrinsic to the code, complicated, and need to always work (the obvious exception is reflection which can be used to view even private methods in most cases, when SecurityManager is not configured to prevent this)

Creating an SDK for community consumption.

Here public takes on a wholly different meaning, since this is code that the whole world may see (not just internal to my application). We put code into private methods if we don’t want the SDK users to see it – we don’t see this as code smell, merely as how SDK programming works. But we need to test my private methods, and they are where the functionality of my SDK actually lives.

To test legacy code with large and quirky classes, it is often very helpful to be able to test the one private (or public) method

To test legacy code with large and quirky classes, it is often very helpful to be able to test the one private (or public) method.

We can use the junitx.util.PrivateAccessor package.

[pastacode lang=”java” manual=”import%20junitx.util.PrivateAccessor%3B%0A%0APrivateAccessor.setField(myObjectReference%2C%20%22myCrucialButHardToReachPrivateField%22%2C%20myNewValue)%3B%0APrivateAccessor.invoke(myObjectReference%2C%20%22privateMethodName%22%2C%20java.lang.Class%5B%5D%20parameterTypes%2C%20java.lang.Object%5B%5D%20args)%3B” message=”Java Code” highlight=”” provider=”manual”/]

In the Spring Framework we can test private methods using this method:

ReflectionTestUtils.invokeMethod()

For example:

ReflectionTestUtils.invokeMethod(TestClazz, “createTest”, “input data”);

Generic function to test private fields:

[pastacode lang=”java” manual=”protected%20%3CF%3E%20F%20getPrivateField(String%20fieldName%2C%20Object%20obj)%0A%20%20%20%20throws%20NoSuchFieldException%2C%20IllegalAccessException%0A%20%7B%0A%20%20%20%20Field%20field%20%3Dobj.getClass().getDeclaredField(fieldName)%3B%0A%0A%20%20%20%20field.setAccessible(true)%3B%0A%20%20%20%20return%20(F)field.get(obj)%3B%0A%7D” message=”Java Code” highlight=”” provider=”manual”/] [ad type=”banner”]

If using Spring, ReflectionTestUtils provides some tools that help out with minimal effort.

For example, to set up a mock on a private member without being forced to add an undesirable public setter:

ReflectionTestUtils.setField(theClass, “theUnsettableField”, theMockObject);

Using the Java reflection API, Two examples:

Calling methods, e.g. private void method(String s) – by Java reflection

[pastacode lang=”java” manual=”Method%20method%20%3D%20targetClass.getDeclaredMethod(%22method%22%2C%20String.class)%3B%0Amethod.setAccessible(true)%3B%0Areturn%20method.invoke(targetObject%2C%20%22mystring%22)%3B” message=”Java Code” highlight=”” provider=”manual”/]

Calling methods, e.g. private void method(String s) – by Picklock

[pastacode lang=”java” manual=”interface%20Accessible%20%7B%0A%20%20void%20method(String%20s)%3B%0A%7D%0A%0A…%0AAccessible%20a%20%3D%20ObjectAccess.unlock(targetObject).features(Accessible.class)%3B%0Aa.method(%22mystring%22)%3B%0A” message=”Java Code” highlight=”” provider=”manual”/] [ad type=”banner”]

Setting fields, e.g. private BigInteger amount; – by Java reflection

[pastacode lang=”java” manual=”Field%20field%20%3D%20targetClass.getDeclaredField(%22amount%22)%3B%0Afield.setAccessible(true)%3B%0Afield.set(object%2C%20BigInteger.valueOf(42))%3B%0A” message=”Java Code” highlight=”” provider=”manual”/]

Setting fields, e.g. private BigInteger amount; – by Picklock

[pastacode lang=”java” manual=”interface%20Accessible%20%7B%0A%20%20void%20setAmount(BigInteger%20amount)%3B%0A%7D%0A%0A…%0AAccessible%20a%20%3D%20ObjectAccess.unlock(targetObject).features(Accessible.class)%3B%0Aa.setAmount(BigInteger.valueOf(42))%3B%0A” message=”Java Code” highlight=”” provider=”manual”/]

Categorized in: