Categories
java junit tdd unit-testing

How do I test a class that has private methods, fields or inner classes?

3089

How do I use JUnit to test a class that has internal private methods, fields or nested classes?

It seems bad to change the access modifier for a method just to be able to run a test.

6

  • 304

    Best way to test a private method is not testing it directly

    – Surya

    Aug 30, 2010 at 20:43

  • 28

    Check the article Testing Private Methods with JUnit and SuiteRunner.

    Oct 13, 2010 at 9:34


  • 1

    why should test a private function ? It will automatically be tested anyway (and must be tested) when you test the feature/method which is using it the private function.

    Sep 25, 2021 at 19:59


  • 3

    I’ve rolled this question back to its original state, prior to generifying the question. In its current state, the answers are highly Java-oriented, and the question was largely focused on the “how”, meaning that the later versions erasing Java and generalizing for other languages, and at the end flipping the focus to C++ invalidates far too many of the answers. A generalized form asking “how to” in any arbitrary language and framework would also be considered far too broad, meaning the last few edits pushed this question towards being closed rather than being constructive.

    Oct 19, 2021 at 20:43

  • 1

    @AkashVerma: For the same reason you want to do unit tests instead of just a system test?

    Jun 30 at 10:25

1795

If you have somewhat of a legacy Java application, and you’re not allowed to change the visibility of your methods, the best way to test private methods is to use reflection.

Internally we’re using helpers to get/set private and private static variables as well as invoke private and private static methods. The following patterns will let you do pretty much anything related to the private methods and fields. Of course, you can’t change private static final variables through reflection.

Method method = TargetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

And for fields:

Field field = TargetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

Notes:

  1. TargetClass.getDeclaredMethod(methodName, argClasses) lets you look into private methods. The same thing applies for
    getDeclaredField.
  2. The setAccessible(true) is required to play around with privates.

2

  • 397

    Useful if you don’t know the API perhaps, but if you are having to test private methods in this manner there is something up with your design. As another poster says unit testing should test the class’s contract: if the contract is too broad and instantiates too much of the system then the design should be addressed.

    – andygavin

    Jun 26, 2009 at 14:23

  • 4

    We develop methods that do a single specific task that allow the class to perform its specific task. These methods should not be public and still need to be tested independently. So yes reflection is a good way to do this and no your design does not need review if you are using reflection for this purpose.

    Oct 2, 2021 at 12:05

775

The best way to test a private method is via another public method. If this cannot be done, then one of the following conditions is true:

  1. The private method is dead code
  2. There is a design smell near the class that you are testing
  3. The method that you are trying to test should not be private

7

  • 13

    Further, we never get close to 100% code coverage anyway, so why not focus your time doing quality testing on the methods that clients will actually be using directly.

    – grinch

    Feb 13, 2013 at 20:29

  • 57

    @grinch Spot on. The only thing you would gain from testing private methods is debugging information, and that’s what debuggers are for. If your tests of the class’s contract have full coverage then you have all the information you need. Private methods are an implementation detail. If you test them you will have to change your tests every time your implementation changes, even if the contract doesn’t. In the full life cycle of the software this is likely to cost a lot more than the benefit it gives.

    Jun 25, 2013 at 7:53

  • 13

    I am impressed how often the “should not be private” claim is repeated across the answers here, as if “make it public so you can test it” could not easily lead to code-smell that invites others to abuse parts of a class. Exposing sensible internals just for easier testing of various code paths isn’t always sensible, so don’t follow this device here blindly!

    – dube

    Jun 8, 2021 at 12:16

  • 1

    The “should not be private” here doesn’t say “just make it public for test”. If there is a need for testing the private method, there must be something like the three conditions he mentioned here. If you want 100% test coverage, that’s still possible by calling the public methods of the class with various parameters, except when it is unused or contains dead code, eg. if (x == null) which is never reached because you nullchecked in the public method already. But then you should cleanup the private method, instead of inventing test cases that cannot happen.

    – Jens

    Jul 8, 2021 at 10:34

  • 3

    A counterexample (real) situation where none of these 3 points is valid (as far as I can think): A public method foo() will 1. use a private method bar() and 2. run in an infinite loop. As far as I know you can’t test bar() by calling foo() otherwise the test case will run forever.

    Nov 23, 2021 at 11:27


368

When I have private methods in a class that are sufficiently complicated that I feel the need to test the private methods directly, that is a code smell: my class is too complicated.

My usual approach to addressing such issues is to tease out a new class that contains the interesting bits. Often, this method and the fields it interacts with, and maybe another method or two can be extracted in to a new class.

The new class exposes these methods as ‘public’, so they’re accessible for unit testing. The new and old classes are now both simpler than the original class, which is great for me (I need to keep things simple, or I get lost!).

Note that I’m not suggesting that people create classes without using their brain! The point here is to use the forces of unit testing to help you find good new classes.

3

  • Why create a new class when you can make your method public anyway?

    – Farid

    Nov 16, 2021 at 17:47

  • If you have a mix of private and public methods on a class, that’s a hint that multiple responsibilities are present.

    Nov 17, 2021 at 18:27

  • Use reflection to access the private method in a test. For example, i have an implementation of an algorithm in a private method and this method is used in another public method. So i need to test this algorithm properly (even while i am writing this algorithm). So why do i need to do a hack in the productive code only to be able to test this method? Yes, using java reflection is also a hack, but only in the test. And if i decide to move the method (for some other reason) in to a utils class, i can just move the test too .. done. Easy peasy, readable, maintainable.

    Jan 24 at 10:17