1

I started to use JUnit and Mockito in my projects, what I have noticed quickly is I ended up converting my private methods to public in order to be accesed from test classes, which is a terrible solution.

Sometimes it is sufficient to test only the public methods, but sometimes i want to really test some internal methods as well. Is there a workaround for this? for example a special annotation that allows JUnit to mock a private method as public or something like that?

Spring
  • 11,333
  • 29
  • 116
  • 185
  • 1
    No need to make them public, just make them package protected (no qualifiers: "void testFoo()") and put your tests in the same package. – Cedric Beust Apr 19 '12 at 22:55

4 Answers4

5

Your public methods must be calling your private methods. So you can test your private method by making a test function of your public method.

If you still want to test private function by Junits, you can do it by using reflection.

You have to set the property of method setAccessible==true.

Example:

 public void testisvalid() throws Exception 
    {
        MyHandler handler = new MyHandler();
        Method privateStringMethod = MyHandler.class.getDeclaredMethod("isvalid", Long.class);
        privateStringMethod.setAccessible(true);
        String =  (String) privateStringMethod.invoke(handler, 852l );
        assertNotNull(s);
    }

In the getDeclaredMethod you have to give the name of the private method , and the type of the arguments you are passing in the function in order.

vikiiii
  • 9,246
  • 9
  • 49
  • 68
  • IMHO Reflection should only be the last resort. See [Is it bad practice to use Reflection in Unit testing?](http://stackoverflow.com/questions/2811141/is-it-bad-practice-to-use-reflection-in-unit-testing) – Péter Török Apr 23 '12 at 07:26
  • @Peter I know it is a bad practice.First line of answers gives the other solution.But i have told If the OP still wants to test Private function by junits, then use reflection. – vikiiii Apr 23 '12 at 07:39
  • Glad we agree on this :-) It was not clear from your answer though (at least to me), so I thought it useful to mention it. – Péter Török Apr 23 '12 at 07:49
5

The need to directly test a private method is a design smell. In a well designed class, all functionality is accessible, sensible and thus testable via its public interface.

The lack of this usually means that your class is too big and complex, trying to handle multiple responsibilities at once. The best solution to this is refactoring: extract some of the functionality into a separate class, where it can be made publicly available and thus directly unit testable.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
  • Great answer. If you focus on testing _behaviour_, rather than _lines of code_, you'll never want your test class to call your private methods. – Dawood ibn Kareem Apr 20 '12 at 22:13
3

The first question to ask is: could these private methods be part of the public interface of an additional helper class. In this case, you could test this helper class, and inject a mock helper in the original class.

If it's not possible, then make these private methods protected, document the fact that they're protected only in order to be tested and that they should not be called or overridden by subclasses, and put the test class in the same packaged as the class under test to be able to access this protected method.

I use the @VisibleForTesting annotation provided by Guava in this case.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
2

My maven build infrastructure provides for the test sources a seperate directory, but with the same package structure. So it suffices if the methods are not public but package accessible.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138