How do I test a class that has private methods, fields or inner classes?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Testing a class with private methods, fields, or inner classes in Java (or similar languages) can be tricky since private members are not accessible directly outside the class. However, there are various techniques and strategies to test such private components indirectly or directly when necessary.
General Strategy: Test Public Methods
The most common and recommended approach is to test private methods indirectly through public methods.
- Why? Private methods are implementation details, and testing them directly can make your tests tightly coupled to the class's internal implementation.
- Public methods should exercise private methods, so testing public methods effectively validates the behavior of private methods.
Example:
Test Code:
Key Idea: The private method doubleValue() is tested indirectly because the public method calculate() relies on it.
1. Use Reflection (Not Recommended for Normal Cases)
Reflection allows you to access private methods or fields directly at runtime. This is useful in edge cases, but it should be avoided unless absolutely necessary because it breaks encapsulation.
Example: Testing a Private Method Using Reflection
Explanation:
getDeclaredMethod()retrieves the private method.setAccessible(true)allows access to the private method.invoke()calls the method with the provided arguments.
2. Use a Helper Class or Package-Private Access
If private methods are complex and need direct testing, you can refactor them to:
- Package-private access: Remove
privateand make the method package-private (default access modifier). - Helper Class: Extract private methods into a new helper class that can be tested directly.
Refactoring Example:
Test Code:
3. Use Mocking to Test Private Dependencies
When private fields or methods depend on other classes, you can use mocking libraries like Mockito or PowerMockito to test behavior.
Example: Mocking a Private Field
If a private field is a dependency, you can use reflection or frameworks to set it for testing.
4. Test Inner Classes
For testing private inner classes, you can use reflection to access them or change their access to package-private.
Example:
Test Code (Indirect Test):
If you need to test Inner directly, reflection or extracting it to a separate class will be required.
Best Practices
- Test through public methods: This validates the behavior rather than the implementation details.
- Refactor private methods: Extract complex logic into package-private or helper classes.
- Avoid overusing reflection: Reflection breaks encapsulation and makes tests fragile.
- Mock dependencies: Use mocking tools like Mockito for private fields or behaviors.
Summary
| What to Test | Solution |
| Private Methods | Test indirectly via public methods. |
| Complex Private Methods | Refactor into a helper class or package-private. |
| Private Fields | Use reflection or mocking to inject dependencies. |
| Private Inner Classes | Test via the outer class or use reflection. |
Testing private members directly is generally discouraged because private code is part of the implementation, and tests should focus on observable behavior via public interfaces. 🚀

