0

I know how I can access a private method or field from my Class from within a Test class:

To access a private method from MyClass, named void doSomething():

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
...

try {
    Method method = MyClass.class.getDeclaredMethod("doSomething", (Class[])null); // (Class[])null is for parameterless methods
    method.setAccessible(true);
    method.invoke(localInstanceOfMyClass);
}
catch (NoSuchMethodException ex){
    ex.printStackTrace();
}
catch (IllegalAccessException ex){
    ex.printStackTrace();
}
catch (IllegalArgumentException ex){
    ex.printStackTrace();
}
catch (InvocationTargetException ex) {
    ex.printStackTrace();
}

To access a private field from MyClass, named boolean myField:

import java.lang.reflect.Field;
...

try {
    Field field = MyClass.class.getDeclaredField("myField");
    field.setAccessible(true);
    field.set(localInstanceOfMyClass, true); // true is the value I want to assign to myField
}
catch (NoSuchFieldException ex){
    ex.printStackTrace();
}
catch (IllegalAccessException ex){
    ex.printStackTrace();
}
catch (IllegalArgumentException ex){
    ex.printStackTrace();
}

(source: https://stackoverflow.com/a/34658/1682559)

As you can see this is quite a lot of code for just putting a private boolean on true or false.


So, my question: Is it possible to somehow make two public static methods, two for Method and one for Field, that I can use in all my Test Classes? To clarify:

TestMethodsClass.setPrivateField(... some parameters ...);
TestMethodsClass.runPrivateVoidMethod(... some parameters ...);
TestMethodsClass.runPrivateReturnMethod(... some parameters ...);

Example of parameters based on examples void doSomething() en boolean myField above:

TestMethodsClass.setPrivateField(localInstanceOfMyClass, "myField", true);
TestMethodsClass.runPrivateVoidMethod(localInstanceOfMyClass, "doSomething", null);
// PS: null will be converted in the method itself to (Class[])null`

Thanks in advance for the responses.

Community
  • 1
  • 1
Kevin Cruijssen
  • 9,153
  • 9
  • 61
  • 135

1 Answers1

0

Ok, it was actually pretty easy..

TestMethodsClass:

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestMethodsClass
{
    public static void runPrivateVoidMethod(Object ob, String methodName, Class<?>[] parameters){
        try {
            Method method = null;
            if(parameters == null){
                Class<?>[] nullParameter = (Class[])null;
                method = ob.getClass().getDeclaredMethod(methodName, nullParameter);
            }
            else
                method = ob.getClass().getDeclaredMethod(methodName, parameters);

            if(method != null){
                method.setAccessible(true);
                method.invoke(ob);
            }
        }
        catch (NoSuchMethodException ex){
            ex.printStackTrace();
        }
        catch (IllegalAccessException ex){
            ex.printStackTrace();
        }
        catch (IllegalArgumentException ex){
            ex.printStackTrace();
        }
        catch (InvocationTargetException ex) {
            ex.printStackTrace();
        }
    }

    public static Object runPrivateReturnMethod(Object ob, String methodName, Class<?>[] parameters){
        Object returnObject = null;
        try {
            if(parameters == null){
                Class<?>[] nullParameter = (Class[])null;
                Method method = ob.getClass().getDeclaredMethod(methodName, nullParameter);
                method.setAccessible(true);
                returnObject = method.invoke(ob);
            }
            else{
                Method method = ob.getClass().getDeclaredMethod(methodName, parameters);
                method.setAccessible(true);
                method.invoke(ob);
            }
        }
        catch (NoSuchMethodException ex){
            ex.printStackTrace();
        }
        catch (IllegalAccessException ex){
            ex.printStackTrace();
        }
        catch (IllegalArgumentException ex){
            ex.printStackTrace();
        }
        catch (InvocationTargetException ex) {
            ex.printStackTrace();
        }
        return returnObject;
    }

    public static void setPrivateField(Object ob, String fieldName, Object value){
        try {
            Field field = ob.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(ob, value);
        }
        catch (NoSuchFieldException ex){
            ex.printStackTrace();
        }
        catch (IllegalAccessException ex){
            ex.printStackTrace();
        }
        catch (IllegalArgumentException ex){
            ex.printStackTrace();
        }
    }
}

How to call it:

// Set private field "boolean myField" from MyClass to true
TestMethodsClass.setPrivateField(localInstanceOfMyClass, "myField", true);

// Run private method "doSomething()" from MyClass
TestMethodsClass.runPrivateVoidMethod(localInstanceOfMyClass, "doSomething", null);

// Run private method "doSomething()" from MyClass and assign the return value to a local field
boolean test = (boolean)TestMethodsClass.runPrivateReturnMethod(localInstanceOfMyClass, "doSomething", null);

I haven't tested it completely yet, so I don't know if it works for all types. But Strings and booleans work pretty well as far as I can tell. Will do some more testing later on, when I have some spare time from my Project.

Kevin Cruijssen
  • 9,153
  • 9
  • 61
  • 135