How to use JUnit 5 to test for private methods

JUnit is a widely used open-source testing framework for Java applications. It provides a simple and effective way to write unit tests, ensuring the reliability and correctness of our code. With JUnit, we can define assertions and test cases to verify the expected behavior of individual units of code, such as classes or methods.

Private method

For JUnit, private methods refer to methods declared as private within a Java class and intended to be used internally by that class. Private methods are not directly accessible or testable from JUnit test cases since they are considered implementation details and are not part of the public API. While JUnit does not provide direct mechanisms to test private methods, there are alternative approaches, like using reflection or extracting private functionality into separate methods that can be tested indirectly.

Reflection

Java's reflection API allows us to access and invoke private methods dynamically. We can use reflection in our test methods to access and invoke the private methods of the class we want to test.

package io.educative.junit5;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.junit.jupiter.api.Assertions.assertEquals;
class PrivateClassTest {
class TestClass {
private int privateMethodName(int number) {
System.out.println(number + 10);
return number + 10;
}
}
@Test
void testPrivateMethod() throws Exception {
TestClass TestClass = new TestClass();
Method privateMethod = TestClass.class.getDeclaredMethod("privateMethodName", int.class);
privateMethod.setAccessible(true);
int result = (int) privateMethod.invoke(TestClass, 10);
assertEquals(20, result);
}
}

Explanation

Line 6: We initialize the inner class TestClass within PrivateClassTest.

Line 7: We define a private method that takes an integer argument number and returns an integer.

Lines 8–10: We print the sum of number and 10 to the console. This line is used for demonstration purposes to show the output of the private method.

Line 15: The @Test input indicates that the following method is a test case.

Line 16: Defines the test case method named testPrivateMethod. It throws the Exception class to handle any exceptions during test execution.

Line 18: We retrieve the privateMethodName method from the TestClass class using reflection. It uses getDeclaredMethod to access a private method and specifies the method name and argument types.

Line 19: We enable access to the private method by setting its accessibility to true since private methods are not directly accessible by default.

Line 20: We invoke the private method on the TestClass instance using reflection. It passes TestClass as the object on which the method is invoked and 10 as the argument to the method.

Line 21: We compare the result value with the expected value of 20 using the assertEquals method. If the values don't match, an assertion error will indicate failure.

Extract private functionality into a helper method

Suppose the private method contains significant functionality that needs to be tested. In that case, we can consider extracting that functionality into a separate helper method and making it a package-private (default access level) instead of private. This way, the helper method can be tested directly, and the private method can remain as a thin wrapper around it.

public class MathUtils {
public int multiplyByTwo(int number) {
return multiply(number, 2);
}
private int multiply(int a, int b) {
return a * b;
}
}

Explanation

Lines 1–4: The MathUtils class contains two methods: multiplyByTwo which is a public method, and multiply which is a private helper method used to perform the actual multiplication operation.

Lines 6–9: The multiplyByTwo method calls the multiply method internally, passing the input number and the value 2 as arguments. It returns the multiplication result, which is the input number multiplied by 2.

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved