Bird
Raised Fist0
JUnittesting~5 mins

Testing private methods (should you?) in JUnit

Choose your learning style10 modes available
Introduction

Private methods are hidden helpers inside a class. Testing them directly can make tests fragile. Instead, test the public behavior that uses them.

When you want to ensure the main features of your class work correctly.
When private methods are complex but only used internally.
When you want to avoid breaking tests if internal code changes but behavior stays the same.
When you want to keep tests simple and focused on what users see.
When refactoring code and you want to keep tests stable.
Syntax
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.

Examples
Private method doubleValue is used inside public method addOneAfterDouble.
JUnit
public class Calculator {
    private int doubleValue(int x) {
        return x * 2;
    }

    public int addOneAfterDouble(int x) {
        return doubleValue(x) + 1;
    }
}
Test calls only the public method addOneAfterDouble. Private method is tested indirectly.
JUnit
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));
    }
}
Sample Program

This test checks the public method addOneAfterDouble. It indirectly tests the private method doubleValue by verifying the final result.

JUnit
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));
    }
}
OutputSuccess
Important Notes

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.

Summary

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

(1/5)
1. Why is it generally discouraged to write JUnit tests that directly test private methods?
easy
A. Because private methods cannot be accessed by JUnit at all.
B. Because private methods are implementation details and should be tested indirectly through public methods.
C. Because testing private methods requires special annotations that are not supported.
D. Because private methods always contain trivial code that doesn't need testing.

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    Because private methods are implementation details and should be tested indirectly through public methods. -> Option B
  4. Quick Check:

    Test behavior, not private code [OK]
Hint: Test public methods to cover private ones indirectly [OK]
Common Mistakes:
  • Trying to access private methods directly with reflection
  • Assuming private methods don't need testing at all
  • Confusing private with protected or public methods
2. Which of the following is a correct way to test private methods in JUnit without changing their access modifier?
easy
A. Use reflection to invoke the private method directly in the test.
B. Change the private method to public and test it directly.
C. Test the private method indirectly by calling the public method that uses it.
D. Use a special JUnit annotation @TestPrivate to test private methods.

Solution

  1. Step 1: Review JUnit capabilities

    JUnit does not provide a built-in annotation to test private methods directly.
  2. Step 2: Identify best practice

    Testing private methods indirectly through public methods is the recommended approach without changing access modifiers or using reflection.
  3. Final Answer:

    Test the private method indirectly by calling the public method that uses it. -> Option C
  4. Quick Check:

    Test via public interface [OK]
Hint: Test private logic through public methods only [OK]
Common Mistakes:
  • Using reflection unnecessarily
  • Changing method visibility just for testing
  • Expecting JUnit to support private method testing directly
3. Consider the following Java class snippet:
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?
medium
A. Assert.assertEquals(6, new Calculator().square(2));
B. Assert.assertEquals(9, new Calculator().multiply(3, 3));
C. Assert.assertEquals(6, new Calculator().multiply(2, 3));
D. Assert.assertEquals(9, new Calculator().square(3));

Solution

  1. Step 1: Identify accessible methods

    The multiply method is private and cannot be called directly in tests.
  2. Step 2: Use public method that calls private method

    The square method calls multiply internally, so testing square indirectly tests multiply.
  3. Final Answer:

    Assert.assertEquals(9, new Calculator().square(3)); -> Option D
  4. Quick Check:

    Test private via public method [OK]
Hint: Test private logic by calling public methods that use it [OK]
Common Mistakes:
  • Trying to call private method directly in test
  • Confusing expected results for square vs multiply
  • Using wrong assertion values
4. You have the following test code trying to test a private method using reflection:
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?
medium
A. Reflection breaks encapsulation and makes tests fragile to implementation changes.
B. The method.invoke call will always throw an exception for private methods.
C. JUnit does not support assertions on reflection results.
D. Private methods cannot be found by getDeclaredMethod.

Solution

  1. Step 1: Understand reflection usage

    Reflection can access private methods but bypasses normal access control, breaking encapsulation.
  2. 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.
  3. Final Answer:

    Reflection breaks encapsulation and makes tests fragile to implementation changes. -> Option A
  4. Quick Check:

    Reflection risks fragile tests [OK]
Hint: Avoid reflection; test behavior via public methods [OK]
Common Mistakes:
  • Assuming reflection is always safe for testing
  • Believing private methods cannot be accessed by reflection
  • Ignoring test maintenance costs
5. You have a class with complex private methods that are hard to test indirectly. What is the best approach to make testing easier while following good design and testing principles?
hard
A. Refactor the complex private methods into a new public helper class and test that class directly.
B. Make all private methods public temporarily during testing and revert after tests.
C. Use reflection to test private methods directly in all test cases.
D. Ignore testing private methods since they are internal and assume they work.

Solution

  1. Step 1: Identify testing challenges with complex private methods

    Complex private methods can be difficult to test indirectly and may indicate design issues.
  2. Step 2: Apply refactoring for better testability

    Extracting complex logic into a new public helper class allows direct testing and improves code clarity.
  3. Final Answer:

    Refactor the complex private methods into a new public helper class and test that class directly. -> Option A
  4. Quick Check:

    Refactor for testable public classes [OK]
Hint: Extract complex logic to public classes for easier testing [OK]
Common Mistakes:
  • Changing access modifiers just for tests
  • Overusing reflection for private method testing
  • Skipping tests for complex private logic
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard