Generic Top

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

>> CHECK OUT THE COURSE

1. Overview

When writing tests, we'll often encounter a situation where we need to mock a static method. Previous to version 3.4.0 of Mockito, it wasn't possible to mock static methods directly — only with the help of PowerMockito.

In this tutorial, we'll take a look at how we can now mock static methods using the latest version of Mockito.

To learn more about testing with Mockito, check out our comprehensive Mockito series.

Further reading:

Mock Final Classes and Methods with Mockito

Learn how to mock final classes and methods with Mockito.

Mocking Void Methods with Mockito

See how to mock methods that return void using Mockito.

Mocking Exception Throwing using Mockito

Learn to configure a method call to throw an exception in Mockito.

2. A Simple Static Utility Class

The focus of our tests will be a simple static utility class:

public class StaticUtils {

    private StaticUtils() {}

    public static List<Integer> range(int start, int end) {
        return IntStream.range(start, end)
          .boxed()
          .collect(Collectors.toList());
    }

    public static String name() {
        return "Baeldung";
    }
}

For demonstration purposes, we have one method with some arguments and another one that simply returns a String.

3. Dependencies

Let's get started by adding the mockito-inline dependency to our pom.xml:

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

It's worth noting that at some point, as per the documentation, this functionality may well be integrated into the more familiar mockito-core dependency.

4. A Quick Word on Testing Static Methods

Generally speaking, some might say that when writing clean object-orientated code, we shouldn't need to mock static classes. This could typically hint at a design issue or code smell in our application.

Why? First, a class depending on a static method has tight coupling, and second, it nearly always leads to code that is difficult to test. Ideally, a class should not be responsible for obtaining its dependencies, and if possible, they should be externally injected.

So, it's always worth investigating if we can refactor our code to make it more testable. Of course, this is not always possible, and sometimes we need to mock static methods.

5. Mocking a No Argument Static Method

Let's go ahead and see how we can mock the name method from our StaticUtils class:

@Test
void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {
    assertThat(StaticUtils.name()).isEqualTo("Baeldung");

    try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
        utilities.when(StaticUtils::name).thenReturn("Eugen");
        assertThat(StaticUtils.name()).isEqualTo("Eugen");
    }

    assertThat(StaticUtils.name()).isEqualTo("Baeldung");
}

As previously mentioned, since Mockito 3.4.0, we can use the Mockito.mockStatic(Class<T> classToMock) method to mock invocations to static method calls. This method returns a MockedStatic object for our type, which is a scoped mock object.

Therefore, in our unit test above, the utilities variable represents a mock with a thread-local explicit scope. It's important to note that scoped mocks must be closed by the entity that activates the mock. This is why we define our mock within a try-with-resources construct so that the mock is closed automatically when we finish with our scoped block.

This is a particularly nice feature since it assures that our static mock remains temporary. As we know, if we're playing around with static method calls during our test runs, this will likely lead to adverse effects in our test results due to the concurrent and sequential nature of running tests.

On top of this, another nice side effect is that our tests will still run quite fast since Mockito doesn't need to replace the classloader for every test.

In our example, we reiterate this point by checking, before and after our scoped block, that our static method name returns a real value.

6. Mocking a Static Method With Arguments

Now let's see another common use case when we need to mock a method that has arguments:

@Test
void givenStaticMethodWithArgs_whenMocked_thenReturnsMockSuccessfully() {
    assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);

    try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
        utilities.when(() -> StaticUtils.range(2, 6))
          .thenReturn(Arrays.asList(10, 11, 12));

        assertThat(StaticUtils.range(2, 6)).containsExactly(10, 11, 12);
    }

    assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
}

Here, we follow the same approach, but this time we use a lambda expression inside our when clause where we specify the method along with any arguments that we want to mock. Pretty straightforward!

7. Conclusion

In this quick article, we've seen a couple of examples of how we can use Mockito to mock static methods. To sum up, Mockito provides a graceful solution using a narrower scope for mocked static objects via one small lambda.

As always, the full source code of the article is available over on GitHub.

Generic bottom

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

>> CHECK OUT THE COURSE
Junit footer banner
1 Comment
Oldest
Newest
Inline Feedbacks
View all comments
Comments are closed on this article!