如何测试私有静态的私有方法 class

How to test private method of a private static class

我如何对私有静态方法中的私有方法进行单元测试 class。

 public class ProjectModel {
          //some code
        private static class MyStaticClass{
            private model (Object obj, Map<String , Object> model)
          }
}

我试图意识到它给出了 NoSuchMethodException

Method method = projectModel.getClass().getDeclaredMethod("model", methodParameters);

一般测试私有方法,类不推荐。如果您仍想测试一些非 public 功能,我建议使用此类方法 类 而不是 private,而是 package private 并将您的测试用例放在相同的包(但像通常在 maven 项目中那样进入单独的源目录)。

您的特定反射问题可以使用

解决
Class.forName(ProjectModel.class.getName()+"$MyStaticClass")
    .getDeclaredMethod("model", methodParameters);

但我不建议使用这种方法,因为将来很难支持这种测试用例。

您可以尝试此代码来解决异常:

Method method = projectModel.getClass().getDeclaredClasses()[0]
    .getDeclaredMethod("model", methodParameters);

出于测试目的,您可以尝试使用以下代码调用 model 方法:

Class<?> innerClass = projectModel.getClass().getDeclaredClasses()[0];

Constructor<?> constructor = innerClass.getDeclaredConstructors()[0];
constructor.setAccessible(true);

Object mystaticClass = constructor.newInstance();
Method method = mystaticClass.getClass().getDeclaredMethod("model", new Class[]{Object.class,Map.class});

method.setAccessible(true);  
method.invoke(mystaticClass, null, null);

假设您的 class ProjectModel 在包 privateaccessor.tst 中并且您的非静态方法 model returns 和 int.

package privateaccessor.tst;
public class ProjectModel {
  //some code
  private static class MyStaticClass{
    private int model (Object obj, Map<String , Object> model) {
      return 42;
    }
  }
}

然后在您的测试中您可以使用反射来获取私有 class' Class 对象并创建一个实例。然后你可以使用 PrivateAccessor (包含在 Junit Addons 中)调用方法 model().

@Test
public void testPrivate() throws Throwable {
  final Class clazz = Class.forName("privateaccessor.tst.ProjectModel$MyStaticClass");
  // Get the private constructor ...
  final Constructor constructor = clazz.getDeclaredConstructor();
  // ... and make it accessible.
  constructor.setAccessible(true);
  // Then create an instance of class MyStaticClass.
  final Object instance = constructor.newInstance();
  // Invoke method model(). The primitive int return value will be
  // wrapped in an Integer.
  final Integer result = (Integer) PrivateAccessor.invoke(instance, "model", new Class[]{Object.class, Map.class}, new Object[]{null, null});
  assertEquals(42, result.intValue());
}