1

How can i unit test a private method, which is in a private static class.

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

I tried to realise that its give NoSuchMethodException

Method method = projectModel.getClass().getDeclaredMethod("model", methodParameters);
RishiKesh Pathak
  • 2,122
  • 1
  • 18
  • 24
  • 4
    First you should ask yourself: do I really need to write unit tests for private methods? If you do want to test them, you shouldn't test them directly, but through the public methods that use them. – Stultuske May 13 '15 at 08:37
  • Two things: 1: this won't compile, as `model()` does not have a return type. 2: private methods don't need testing. Instead you should make sure that the non-private methods this one is used by return correct results. – Dragondraikk May 13 '15 at 08:38
  • You're getting a declared method from the outer class. – Mena May 13 '15 at 08:39
  • 2
    it's a valid question. no reason for a downvote... – nano_nano May 13 '15 at 08:40
  • @Mena No the its called form a method inside the static class , and the method which is calling it is public, but i need to test the private method part. – RishiKesh Pathak May 13 '15 at 08:43
  • @RishiKeshPathak again, `projectModel.getClass().getDeclaredMethod` gets a method of `ProjectModel`, unless you named your instance `projectModel` but it's an instance of `MyStaticClass`. – Mena May 13 '15 at 08:46
  • IMO Testing the methods that use this private static class should be sufficient – Nitin Dandriyal May 13 '15 at 08:47

3 Answers3

3

Assuming your class ProjectModel is in package privateaccessor.tst and your non-static method model returns an int.

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

Then in your test you can use reflection to get the private class' Class object and create an instance. Then you can use the PrivateAccessor (contained in Junit Addons) to call method 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());
}
vanje
  • 10,180
  • 2
  • 31
  • 47
1

You can try this code to resolve the exception :

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

For testing purpose, you can try below code to invoke model method:

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);
Sachin Gupta
  • 7,805
  • 4
  • 30
  • 45
0

In general testing of the private methods and classes is not recommended. If you still want to test some non-public functionality, I'd suggest to make such methods and classes not private, but package private and place your test cases in the same package (but into separate source directory like it's usually done in maven projects).

Your particular reflection issue can be solved using

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

But I would not recommend using such approach as it will be hard to support such test cases in future.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334