Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

One of the challenges of unit testing is mocking private methods.

In this tutorial, we’ll learn about how we can achieve this by using the PowerMock library – which is supported by JUnit and TestNG.

PowerMock integrates with mocking frameworks like EasyMock and Mockito and is meant to add additional functionality to these – such as mocking private methods, final classes, and final methods, etc.

It does that by relying on bytecode manipulation and an entirely separate classloader.

2. Maven Dependencies

First, let’s add required dependencies to use PowerMock with Mockito and JUnit into our pom.xml:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.7.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.9</version>
    <scope>test</scope>
</dependency>

The latest versions can be checked here and here.

3. Example

Let’s get started with an example of a LuckyNumberGenerator. This class has a single public method for generating a lucky number:

public int getLuckyNumber(String name) {
    saveIntoDatabase(name);
    if (name == null) {
        return getDefaultLuckyNumber();
    }
    return getComputedLuckyNumber(name.length());
}

4. Variations in Mocking of Private Methods

For exhaustive unit testing of the method, we’d need to mock private methods.

4.1. Method With No Arguments but With Return Value

As a simple example, let’s mock the behavior of a private method with no arguments and force it to return the desired value:

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());

when(mock, "getDefaultLuckyNumber").thenReturn(300);

In this case, we mock the private method getDefaultLuckyNumber and make it return a value of 300.

4.2. Method With Argument and Return Value

Next, let’s mock the behavior of a private method with an argument and force it to return the desired value:

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());

doReturn(1).when(mock, "getComputedLuckyNumber", ArgumentMatchers.anyInt());

In this case, we mock the private method and make it return 1.

Notice that we don’t care about the input argument and use ArgumentMatchers.anyInt() as a wildcard.

4.3. Verification of Invocation of a Method

Our final strategy is to use PowerMock to verify the invocation of a private method:

LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());
int result = mock.getLuckyNumber("Tyranosorous");

verifyPrivate(mock).invoke("saveIntoDatabase", ArgumentMatchers.anyString());

5. A Word of Caution

Finally, although private methods can be tested using PowerMock, we must be extra cautious while using this technique.

Given the intent of our testing is to validate the behavior of a class, we should refrain from changing the internal behavior of the class during unit testing.

Mocking techniques should be applied to the external dependencies of the class and not to the class itself.

If mocking of private methods is essential for testing our classes, it usually indicates a bad design.

6. Conclusion

In this quick article, we showed how PowerMock could be used to extend the capability of Mockito for mocking and verification of private methods in the class under test.

The source code of this tutorial can be found over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.