Private methods are hidden helpers inside a class. Testing them directly can make tests fragile. Instead, test the public behavior that uses them.
Testing private methods (should you?) in JUnit
public class MyClass { private int helper(int x) { return x * 2; } public int calculate(int y) { return helper(y) + 1; } }
Private methods cannot be called directly from test classes.
Test the public methods that use private methods instead.
doubleValue is used inside public method addOneAfterDouble.public class Calculator { private int doubleValue(int x) { return x * 2; } public int addOneAfterDouble(int x) { return doubleValue(x) + 1; } }
addOneAfterDouble. Private method is tested indirectly.import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; public class CalculatorTest { @Test void testAddOneAfterDouble() { Calculator calc = new Calculator(); assertEquals(5, calc.addOneAfterDouble(2)); } }
This test checks the public method addOneAfterDouble. It indirectly tests the private method doubleValue by verifying the final result.
import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; public class Calculator { private int doubleValue(int x) { return x * 2; } public int addOneAfterDouble(int x) { return doubleValue(x) + 1; } } class CalculatorTest { @Test void testAddOneAfterDouble() { Calculator calc = new Calculator(); assertEquals(5, calc.addOneAfterDouble(2)); assertEquals(11, calc.addOneAfterDouble(5)); } }
Testing private methods directly can make tests fragile and tightly coupled to implementation.
If a private method is very complex, consider refactoring it into a separate class with public methods.
Use reflection to test private methods only as a last resort, because it breaks encapsulation.
Test private methods indirectly through public methods.
Keep tests focused on behavior, not implementation details.
Refactor complex private logic into testable public classes if needed.
Practice
Solution
Step 1: Understand the role of private methods in design
Private methods are internal helpers meant to support public methods and are not part of the class's external behavior.Step 2: Consider testing best practices
Tests should focus on the behavior exposed by public methods, ensuring private methods work correctly as part of that behavior.Final Answer:
Because private methods are implementation details and should be tested indirectly through public methods. -> Option BQuick Check:
Test behavior, not private code [OK]
- Trying to access private methods directly with reflection
- Assuming private methods don't need testing at all
- Confusing private with protected or public methods
Solution
Step 1: Review JUnit capabilities
JUnit does not provide a built-in annotation to test private methods directly.Step 2: Identify best practice
Testing private methods indirectly through public methods is the recommended approach without changing access modifiers or using reflection.Final Answer:
Test the private method indirectly by calling the public method that uses it. -> Option CQuick Check:
Test via public interface [OK]
- Using reflection unnecessarily
- Changing method visibility just for testing
- Expecting JUnit to support private method testing directly
public class Calculator {
private int multiply(int a, int b) {
return a * b;
}
public int square(int x) {
return multiply(x, x);
}
}Which JUnit test will correctly verify the
multiply method's behavior without accessing it directly?Solution
Step 1: Identify accessible methods
Themultiplymethod is private and cannot be called directly in tests.Step 2: Use public method that calls private method
Thesquaremethod callsmultiplyinternally, so testingsquareindirectly testsmultiply.Final Answer:
Assert.assertEquals(9, new Calculator().square(3)); -> Option DQuick Check:
Test private via public method [OK]
- Trying to call private method directly in test
- Confusing expected results for square vs multiply
- Using wrong assertion values
Method method = Calculator.class.getDeclaredMethod("multiply", int.class, int.class);
method.setAccessible(true);
int result = (int) method.invoke(new Calculator(), 2, 3);
Assert.assertEquals(6, result);What is a potential problem with this approach?
Solution
Step 1: Understand reflection usage
Reflection can access private methods but bypasses normal access control, breaking encapsulation.Step 2: Consider test maintenance impact
Tests using reflection are fragile because private method signatures or logic changes can break tests even if public behavior is unchanged.Final Answer:
Reflection breaks encapsulation and makes tests fragile to implementation changes. -> Option AQuick Check:
Reflection risks fragile tests [OK]
- Assuming reflection is always safe for testing
- Believing private methods cannot be accessed by reflection
- Ignoring test maintenance costs
Solution
Step 1: Identify testing challenges with complex private methods
Complex private methods can be difficult to test indirectly and may indicate design issues.Step 2: Apply refactoring for better testability
Extracting complex logic into a new public helper class allows direct testing and improves code clarity.Final Answer:
Refactor the complex private methods into a new public helper class and test that class directly. -> Option AQuick Check:
Refactor for testable public classes [OK]
- Changing access modifiers just for tests
- Overusing reflection for private method testing
- Skipping tests for complex private logic
Ready to prove it?
Pass the test and this pattern moves unknown
