A Guide to Mocking Private and Static Methods Using PowerMock

Mocking a static or private method is often necessary when writing unit tests. However, before Mockito 3.4.0, it was impossible to explicitly mock static methods. Thus, PowerMock offers solutions to the defined use case. In this article, we will look at the introduction of PowerMock and explore examples of mocking private, static, and final methods. So, let’s begin!

To learn more about testing, check out the Testing Java Code tutorials page.

Introduction to PowerMock

PowerMock is a framework that extends other mock libraries, such as Mockito and EasyMock, with more powerful capabilities. It gives additional features like private methods, final classes, final methods, etc. Internally, it makes use of a unique classloader and bytecode manipulation to provide mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers, and more.

Currently, PowerMock supports extension APIs for Mockito and EasyMock only. To make use of PowerMock, we need one of these APIs and a test framework. As of now, PowerMock supports JUnit and TestNG framework.

Project Setup

Let’s assume you have a Maven Spring Boot Project. Refer to this article for more details.

To begin with, add the following dependencies to your Maven project:

<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-module-junit4</artifactId>
  <version>${powermock.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.powermock</groupId>
  <artifactId>powermock-api-mockito2</artifactId>
  <version>${powermock.version}</version>
  <scope>test</scope>
</dependency>
  • Powermock-module-junit4: This library includes Mockito extensions for Powermockito.
     
  • Powermock-api-mockito2: This library includes PowerMockRunner, a custom runner for running tests with PowerMockito.

Basic Steps for Testing with PowerMockito

The fundamental step of testing with PowerMockito is to include the dependencies shared above. The next step is to update the test class with the following two annotations:

  1. @RunWith(PowerMockRunner.class)
  2. @PrepareForTest(fullyQualifiedNames = “com.appsdeveloper.powermockito.introduction.*”)

Here, firstly we have defined the runner to trigger PowerMockRunner and execute all tests using the same. Next, we have used the  @PrepareForTest annotation that represents an array of fully qualified names of types we want to mock. In the example above, we use a package name with a wildcard to tell PowerMockito to prepare all types within the com.appsdeveloper.powermockito.introduction package for mocking.

A simple Utility Class and a Service Component

For the sake of simplicity, we’ve defined a static HelperUtils class that will be used inside a ReportGeneratorService for performing report extraction methods:

ReportGeneratorService.java

package com.appsdeveloper.junitexamples.service;

import com.appsdeveloper.junitexamples.utils.HelperUtils;

public class ReportGeneratorService {

    public String downloadReport() {
        String path = HelperUtils.getUserDirectory();
        // Download Report code
        return path;
    }
}

HelperUtils.java

package com.appsdeveloper.junitexamples.utils;

public class HelperUtils {

    public HelperUtils() {

    }

    public static String getUserDirectory() {
        return "/home/user/Reham";
    }


    public final String getFinalMethod() {
        return "Hello from the Final Method!";
    }

    private String getPrivateMethod() {
        return "Hello from the Private Method!";
    }

    public String privateMethodCaller() {
        return getPrivateMethod() + " Welcome to the Application Developer's Blog";
    }
}

Mocking Private Methods

PowerMockito is an extensive framework that also allows us to mock partially. In the following example, we will illustrate the mocking using the Spy object:

@Test
public void testPrivateMethodCaller() throws Exception {
    HelperUtils helperUtils = new HelperUtils();
    HelperUtils mock = PowerMockito.spy(helperUtils);
    PowerMockito.when(mock, "getPrivateMethod").thenReturn("Hello from the Private Method!");
    String resultFromThePrivateMethodCaller = mock.privateMethodCaller();
    verifyPrivate(mock).invoke("getPrivateMethod");
    assertEquals("Hello from the Private Method! Welcome to the Application Developer's Blog", resultFromThePrivateMethodCaller);
}

In the above, the private method is being called by another public method. We have marked the whole HelperUtils class as a spy and then stubbed the behaviour of the private method. We have set the expectation and then invoked the private method via another public method. Finally, the test makes sure that the return value from the invocation of the private method is the same as per the expectation.

Mocking Final Methods

Similar to the private method testing, we will again use partial mocking of the final method. Firstly, we need to instantiate the class and tell the PowerMockito API to spy on it.

@Test
public void testGetFinalMethod() {
    HelperUtils helperUtils = new HelperUtils();
    HelperUtils mock = PowerMockito.spy(helperUtils);

    PowerMockito.when(mock.getFinalMethod()).thenReturn("Hello from the Final Method!");
    String resultFromTheFinalMethod = mock.getFinalMethod();
    verify(mock).getFinalMethod();
    assertEquals("Hello from the Final Method!", resultFromTheFinalMethod);
}

Next, we stubbed the behaviour of the final method by setting an expectation and invoking the method. Finally, verification is done using the verify() statement. An assertion at the end verifies that calling the getFinalMethod method will return a value that matches the expectation.

Mocking Static Methods

Static methods are really common in our coding practices. Static methods are usually written as a part of utility classes, therefore it is important to validate the behaviour of these methods. To support the testing, PowerMockito offers a way to test out static methods. The following is a test class for the ReportGeneratorService that is responsible to download a report. The method downloadReport() internally calls a method from the HelperUtils class to get the user directory.

package com.appsdeveloper.junitexamples.service;

import com.appsdeveloper.junitexamples.utils.HelperUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.atLeastOnce;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest(fullyQualifiedNames = "com.appsdeveloper.junitexamples.utils.*")
public class ReportGeneratorServiceTest {

    ReportGeneratorService reportGeneratorService;

    @Before
    public void setUp() {
        PowerMockito.mockStatic(HelperUtils.class);
        reportGeneratorService = new ReportGeneratorService();
    }


    @Test
    public void testDownloadReport() {
        when(HelperUtils.getUserDirectory()).thenReturn("/home/reham/");
        String result = reportGeneratorService.downloadReport();
        assertEquals("/home/reham/", result);
        PowerMockito.verifyStatic(HelperUtils.class, atLeastOnce());
        HelperUtils.getUserDirectory();
        PowerMockito.verifyNoMoreInteractions(HelperUtils.class);
    }
}
  •  @PrepareForTest annotation is mandatory to be included in the class under test.
  • Inside the @Before annotation, the initial setup is done.
  • mockStatic(//name of the static class) This is an essential step to mock static methods.
  • Inside the @Test,  a setup of stubbing is done on a static method, and expectations are set accordingly.
  • The actual method of the ReportGeneratorService is called.
  • The assertion is done to verify the output is equal to the expected value.
  • Next, the Verification of a static method is done in two steps:
    1. The first call PowerMockito.verifyStatic(HelperUtils.class) to start verifying behaviour and then
    2. Call the static method of  HelperUtils.class to verify.
    3. Finally, an additional statement is made to verify no further interactions with the HelperUtils class.

Conclusion

In this blog, we’ve introduced the PowerMockito API and shown how it may be used to address some of the issues that developers face when they work with the Mockito framework. We have seen that  Powermock is an extensive framework that comes in handy and useful in such scenarios. We have seen a basic structure to include PowerMockito in your code base and have hands-on examples to show how PowerMock can be used to extend the capability of Mockito for mocking and verification of static, final, and private methods in the class under test.

Looking to expand your testing repertoire? Visit the Testing Java Code page and dive into our comprehensive Mockito tutorials. Discover the versatility of Mockito as you learn effective testing techniques and harness its capabilities to create thorough and accurate tests.