How to test Private Methods using Junit 5

Introduction

Here in this tutorial I will show you an example on how to test private methods using Junit framework. I am using Junit 5 framework to test the private method. Using Mockito framework you won’t be able to test private methods, but using PowerMock core API you will be able to test the private methods. You can also use Java’s Reflection API to test private methods. You can use Spring framework’s ReflectionTestUtils to test your private methods.

You generally don’t want to unit test private methods directly. Since they are private, you would consider them to call from a public method. If the methods that call your private methods are working as you expect, you then assume by extension that your private methods are working correctly. But still I will show you here how to unit test your private methods in Java and Spring applications.

Prerequisites

Java at least 8, Junit 5, PowerMock Core, Mockito, Spring Boot Starter Test

Test Private Method in Java App

Project Setup

For Java based applications you need to configure the following build file for maven based project:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>java-junit-mock-private-methods</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>12</maven.compiler.source>
		<maven.compiler.target>12</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-engine</artifactId>
			<version>5.8.0-M1</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-junit-jupiter</artifactId>
			<version>3.9.0</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.powermock</groupId>
			<artifactId>powermock-core</artifactId>
			<version>2.0.9</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Private Method

First I am going to test private method in Java based application. Consider the following class where I have created a private method called pvMethod().

package com.roytuts.java.junit.mock;

public class PrivateMethodApp {

	private Integer pvMethod(Integer id) {
		System.out.println(id + 10);
		return id + 10;
	}

}

Note important thing is that if you are using Java’s reflection API to test your private method then arguments to the private methods need to be of object class types instead of primitive types. For example, I have used Integer instead of int.

Junit Class

Next I am going to create the following Junit test class to test the above private method.

package com.roytuts.java.junit.mock;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import org.powermock.reflect.Whitebox;

@ExtendWith(MockitoExtension.class)
public class PrivateMethodTest {

	// @Mock
	// private PrivateMethodApp app;

	@InjectMocks
	private PrivateMethodApp app = new PrivateMethodApp();

	@Test
	public void testPrivateMethodUsingReflection() throws NoSuchMethodException, SecurityException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Method method = PrivateMethodApp.class.getDeclaredMethod("pvMethod", Integer.class);
		method.setAccessible(true);
		method.invoke(app, 10);
	}

	@Test
	public void testPrivateMethodUsingPowerMock() throws Exception {
		Whitebox.invokeMethod(app, "pvMethod", 10);
	}

}

To create the mock instance of the PrivateMethodApp, you can use either @Mock or @InjectMocks annotation.

Finally I have created two methods and annotated with @Test annotation to test the private method. testPrivateMethodUsingReflection() – tests using Java’s reflection API and make sure you need to have the class types for the method arguments. testPrivateMethodUsingPowerMock() – tests using PowerMock API and you can have class or primitive types for method arguments.

Executing the above test class will give you the expected output:

test private methods using junit

Test Private Method in Spring App

Now I will show you how to test private method using Spring’s ReflectionTestUtils API.

Project Setup

Now you can add the Spring Boot starter and starter test dependencies into the pom.xml file.

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>java-junit-mock-private-methods</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.5</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>12</maven.compiler.source>
		<maven.compiler.target>12</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>

		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-engine</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-junit-jupiter</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Junit Class

Next I am going to add new test method in the PrivateMethodTest class to test private method using ReflectionTestUtils.

package com.roytuts.java.junit.mock;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;

@ExtendWith(MockitoExtension.class)
public class PrivateMethodTest {

	// @Mock
	// private PrivateMethodApp app;

	@InjectMocks
	private PrivateMethodApp app = new PrivateMethodApp();

	@Test
	public void testPrivateMethodUsingReflectionUtils() throws Exception {
		ReflectionTestUtils.invokeMethod(app, "pvMethod", 10);
	}
	
}

Executing the above test class will give you the following output:

That’s an idea how to test your private methods in Java and Spring applications.

Source Code

Download

Leave a Reply

Your email address will not be published. Required fields are marked *