When writing tests, I sometimes access private methods of objects, I made a simple wrapper function because I can't do it by hitting reflection directly every time.
class Main {
    /**
     *Execute private method of object
     *
     * @param target Instance of the target object
     * @param name method name
     * @param <T>Target object type
     * @throws Exception Exception at method execution
     */
    public static <T> void invokeMethod(T target, String name) throws Exception {
        final Method method = target.getClass().getDeclaredMethod(name);
        method.setAccessible(true);
        method.invoke(target);
    }
    /**
     *Execute private method of object
     *
     * @param target Instance of the target object
     * @param name method name
     * @param parameterValues List of arguments
     * @param <T>Target object type
     * @throws Exception Exception at method execution
     */
    public static <T> void invokeMethod(T target, String name, List<?> parameterValues) throws Exception {
        //Get an array of argument types
        final Class<?>[] parameterTypes = new Class[parameterValues.size()];
        parameterValues.stream().map(Object::getClass).collect(Collectors.toList()).toArray(parameterTypes);
        final Method method = target.getClass().getDeclaredMethod(name, parameterTypes);
        method.setAccessible(true);
        method.invoke(target, parameterValues.toArray());
    }
    /**
     *Execute private method of object
     *
     * @param target Instance of the target object
     * @param name method name
     * @param parameterValues List of arguments
     * @param resultType Class instance of result object
     * @param <T>Target object type
     * @param <U>Return type
     * @return value of return method
     * @throws Exception Exception at method execution
     */
    public static <T, U> U invokeMethod(T target, String name, List<?> parameterValues, Class<U> resultType) throws Exception {
        //Get an array of argument types
        final Class<?>[] parameterTypes = new Class[parameterValues.size()];
        parameterValues.stream().map(Object::getClass).collect(Collectors.toList()).toArray(parameterTypes);
        final Method method = target.getClass().getDeclaredMethod(name, parameterTypes);
        method.setAccessible(true);
        return resultType.cast(method.invoke(target, parameterValues.toArray()));
    }
    static class PrivateMethodTest {
        private void sayHelloWorld() {
            System.out.println(makeHelloMessage("world!"));
        }
        private void sayHello(String message) {
            System.out.println(makeHelloMessage(message));
        }
        private String makeHelloMessage(String message) {
            return "Hello, " + message;
        }
    }
    public static void main(String[] args) throws Exception {
        final PrivateMethodTest target = new PrivateMethodTest();
        invokeMethod(target, "sayHelloWorld");
        final List<Object> params = new ArrayList<>();
        params.add("world!");
        invokeMethod(target, "sayHello", params);
        final String message = invokeMethod(target, "makeHelloMessage", params, String.class);
        System.out.println(message);
    }
}
        Recommended Posts