使用反射来测试内部私有类的方法

时间:2016-06-22 18:30:09

标签: java reflection

有没有办法使用反射来测试私有内部类的方法? 在下面的代码中,我们如何测试func-1和func-2

public class Outer extends AbstractOuter {
private final Properties properties;

public Outer(Properties properties) {
    this.properties = properties;
}

private class Inner extends AbstractInner {

    private int numOfProperties;

    @Override
    void func-1() throws Exception {
        //
    }

    private int func-2(long l)  {
        //
    }
}
}

4 个答案:

答案 0 :(得分:1)

package SalesUnitsIntoCarton.mySolution;

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

public class UtilityReflections {
    private static final Object[] EMPTY = {};

    /**
     * This method returns a value, returned by the method of a private inner class, of a given object instance.
     *
     * @param outerClassInstance This parameter needs to be an instance of the outer class that contains the private inner class.
     * @param attributeNameOfInnerClassInOuterClass This is the name of the attribute that is an inner class type, within the outer class.
     * @param innerClassName This is the class name of the inner class.
     * @param methodNameOfInnerClass This is the name of the method inside the inner class that should be called.
     * @return Returns the value returned by the method of the inner class. CAUTION: needs casting since its of type {@link Object}
     * 
     * @throws SecurityException 
     * @throws NoSuchFieldException 
     * @throws ClassNotFoundException 
     * @throws NoSuchMethodException 
     * @throws InvocationTargetException 
     * @throws IllegalArgumentException 
     * @throws IllegalAccessException 
     * @throws Exception
     */
     public static <T extends Object> Object executeInnerClassMethod(T outerClassInstance, String attributeNameOfInnerClassInOuterClass, String innerClassName, String methodNameOfInnerClass) 
         throws NoSuchFieldException, SecurityException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
         IllegalArgumentException, InvocationTargetException {

         final Class<?> outerClass = outerClassInstance.getClass();

         final Field field = outerClass.getDeclaredField(attributeNameOfInnerClassInOuterClass);
         field.setAccessible(true);

         Class<?> innerClass = Class.forName(innerClassName);
         innerClass = field.getType();

         //access the method
         final Method method = innerClass.getDeclaredMethod(methodName, new Class<?>[]{});
         method.setAccessible(true);
         return method.invoke(field.get(outerClassInstance), EMPTY);
     }
}

答案 1 :(得分:0)

反射和使用setAccessible(true)在某种程度上是可能的,但是特别是因为你有私有的非静态内部类会很难。

最有趣的问题是:你为什么要这么做?

那些内部类和方法应该影响测试的外部类的行为。所以请测试那个班级!

尝试测试类的私有部分主要是延迟测试的信号,因为您可能需要较少的设置,没有测试的遗留代码并且只想测试我的更改。但抱歉,这没用。

  • 您的测试是绑定到实现的白盒测试,而不是类
  • 的api
  • 即使整体行为没有改变,任何内部重构都可能会破坏测试
  • 并且最重要的是:您不测试内部类或私有方法是否以正确的方式使用(或根本不使用)。

这样做的全部努力都是无用的,而是测试全班!

答案 2 :(得分:0)

我没有处理这个问题,但我认为这是一个很好的问题。 我对此并不是100%肯定,但也许这会奏效。

        Outer.class.getDeclaredClasses()[0].getDeclaredMethod("func-1").invoke(null);

我目前没有环境来测试它。但也许有帮助。

答案 3 :(得分:-2)

您可以使用模拟对象使用Mockito进行测试。