How to mock static methods with Mockito

December 16, 2020 No comments Mockito Library Mock Static

1. Introduction

This article will be about mocking static methods with Mockito. We will try to answer the question is even possible to do it and why should we ever mock anything that is static.

2. Static methods

Let's start with a simple definition. Static methods are that methods in Java programs that can be called without creating an instance of the class. A static method belongs to the class rather than the object of a class.

Using static methods in Java is sometimes necessary, however, most developers limit their use to pure functions without external dependencies. Whether we like them or not, we do sometimes have to rely on them and also mock them in unit tests.

3. Mocking static method with Mockito 3.x

The good news is that from the latest Mockito version mocking static methods is finally supported.

To make this possible, a single dependency had to be added to the pom.xml file:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.6.28</version>
    <scope>test</scope>
</dependency>

The latest version of Mockito inline dependency should be found in our Maven Repository.

If you are using mockito-core you will need to replace it with mockito-inline dependency otherwise you will face the following exception:

org.mockito.exceptions.base.MockitoException: 
The used MockMaker SubclassByteBuddyMockMaker does not support the creation of static mocks

Mockito's inline mock maker supports static mocks based on the Instrumentation API.
You can simply enable this mock mode, by placing the 'mockito-inline' artifact where you are currently using 'mockito-core'.
Note that Mockito's inline mock maker is not supported on Android.

Let's consider we have a simple class with a single static method that we will want to mock in the JUnit test:

package com.frontbackend.libraries.mockito;

public final class WelcomeUtil {

    public static String generateWelcome(String name) {
        return String.format("Welcome %s", name);
    }

    private WelcomeUtil() {
    }
}

The test code looks as follows:

package com.frontbackend.libraries.mockito;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;

public class MockitoStaticMethodTest {

    @Test
    public void testMockStaticMethods() {
        assertEquals("Welcome John", WelcomeUtil.generateWelcome("John"));

        try (MockedStatic<WelcomeUtil> theMock = Mockito.mockStatic(WelcomeUtil.class)) {
            theMock.when(() -> WelcomeUtil.generateWelcome("John"))
                   .thenReturn("Guten Tag John");

            assertEquals("Guten Tag John", WelcomeUtil.generateWelcome("John"));
        }

        assertEquals("Welcome John", WelcomeUtil.generateWelcome("John"));
    }
}

There are some things we need to note here:

  • mocked static method will be only visible in the try-with-resources block,
  • different test cases should be tested in different try blocks,
  • static methods could be mocked only using an inline way,
  • after try-with-resource block behavior of the static method will be as originally implemented.

4. Mocking static method with Mockito in older versions 2.x

Now, what about the older version of the Mockito framework? does it support mocking static methods?. The answer is unfortunately NO.

But we could use another library such as PowerMock to mock the static method without using the latest version of Mockito.

First let's start with adding necessery dependencies to our 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">
    <parent>
        <artifactId>libraries</artifactId>
        <groupId>com.frontbackend.libraries</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>powermock</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>2.23.4</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-core</artifactId>
            <version>2.0.9</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-api-mockito2</artifactId>
            <version>2.0.9</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.powermock</groupId>
            <artifactId>powermock-module-junit4</artifactId>
            <version>2.0.9</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

The list of dependencies we used (you can check the latest versions):

The PowerMock uses internal Mockito API so we still need the Mockito library in our dependencies.

The following shows how to create a test that mock the static WelcomeUtil.generateWelcome(...) method just like in the above example:

package com.frontbackend.libraries.powermock;

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

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import com.frontbackend.libraries.powermock.utils.WelcomeUtil;

@RunWith(PowerMockRunner.class)
@PrepareForTest(WelcomeUtil.class)
public class PowermockStaticMethodTest {

    @Test
    public void shouldMockStaticMethodTest() {
        final String value = "Guten Tag John";

        mockStatic(WelcomeUtil.class);

        when(WelcomeUtil.generateWelcome("John")).thenReturn(value);

        assertEquals("Guten Tag John", WelcomeUtil.generateWelcome("John"));
    }
}

5. Conclusion

In this article, we presented how to mock static methods with Mockito from version 3.x. When it is not about mocking methods from third-party libraries, consider refactoring the code so that mocking a static method wouldn't be necessary.

Test examples used in this article, are available in the GitHub Repository:

{{ message }}

{{ 'Comments are closed.' | trans }}