Mocking Static Methods with Mockito (Java & Kotlin)

Last Updated:  March 15, 2023 | Published: October 7, 2020

Want to start a religious discussion? Start asking your teammates whether or not you should mock static method calls. It's debatable if this is an absolute no-go or sometimes a last resort. I agree that you should rethink your implementation if you find yourself googling: Mocking static calls Java. On the other side, there are still valid use cases where this approach is considerable. In the past, PowerMock was the most popular solution for this problem in Java. Starting with version 3.4.0, Mockito now supports mocking static methods.

PS: Before arguing with your co-workers, read through the different opinions around mocking static methods at the corresponding GitHub issue from Mockito.

Required Mockito Maven Setup

Mocking static methods is part of Mockito since version 3.4.0.

If we are using Maven, we can either update our existing Mockito version or include the following dependency to your pom.xml:

If our project uses mockito-core, we'll see the following exception and should replace it with mockito-inline.

When developing an application with Spring Boot and the Spring Boot Starter Test, we can update to Spring Boot Version 2.4.0-M2. This version includes the Mocktio dependency in a compatible version (> 3.4.0).

If our project can't update the main Spring Boot version (yet), we can manually override the used Mockito version using:

And include mockito-inline if required:

Update: Starting with Mockito version 5.0.0, the mockito-inline is now the default MockMaker. If we're using this version, we can skip any manual configuration to use the InlineMockMaker.

Important: The upcoming code examples use Java 11. Not everything will work with Java 8 as expected, as the internals of UUID.toString() did change between those two Java releases.

Mocking Static Methods With Java

Let's take a look at how to use this feature for a Java method that accesses two static methods: UUID.randomUUID() and LocalDateTime.now().

Whether or not this implementation or the corresponding tests make sense is not up for discussion. The example is only for demonstration purposes on how to mock static method calls with Mockito.

With the first test, we want to make sure to use a random UUID whenever we don't pass a parentOrderId:

Here we are using a try-with-resources statement to create a mocked version of the UUID class. This is because MockedStatic extends the ScopedMock interface, which itself extends AutoClosable. The static mocks are thread-local scoped and hence need to be closed.

Inside the try-with-resources statement, we then get access to the mocked version of UUID and can define its behavior using Mockito's well-known when().thenReturn() stubbing setup.

As an alternative, we could also manually call .close() inside @AfterEach.

The same is true when we write a test that includes mocking LocalDateTime.now():

Mocking Static Methods With Method Arguments

Both mocking examples above were using Java's method reference. That's a convenient way to write compact lambda expressions by referring to an existing method.  However, this doesn't apply to mocking every static method.

Let's use the following MyUtils class as an example:

When we now want to mock the static .getWelcomeMessage() method, we can't use the method reference. Mockito's .when() takes a Verification as an argument. This is a functional interface as it has one public method: .apply().

Hence for both UUID.randomUUID() and LocalDateTime.now() we could use their method reference like.when(LocalDateTime::now).

That's not possible for .getWelcomeMessage(String username, boolean isCustomer). If we want to mock this utility method, we can write a custom lambda expression to provide a Verification:

Mocking Static Methods With Kotlin and Mockito

Let's take a look at the OrderService again, but this time we use Kotlin to implement its functionality:

Mocking the static method calls also works here. To write even more idiomatic Kotlin code, we can replace the try-with-resources statement with the use function of the Kotlin standard library:

Since when is a reserved keyword in Kotlin, we have to use the backticks when stubbing the behavior.

Both mockito-kotlin and Mockk seem not to support this yet.

Refactored Alternative to Avoid Mocking Static Methods

As an alternative, let's have a look at how we can avoid mocking static methods for our OrderService. If our project uses a framework that supports dependency injection (e.g., Spring, Jakarta EE with CDI, MicroProfile, Guice), we can slightly refactor our current implementation:

With this approach, we outsource the creation of the orderId to another component.  In addition to this, we use an overloaded version of LocalDateTime.now() that takes a Clock to request the current date & time.

This small refactoring allows us to mock both the Clock and OrderIdGenerator while unit testing our OrderServiceRefactored class:

We can now use standard Mockito functionality to mock the behavior of our external components during the test.

Remember: Having access to a tool does not mean you should always use it.

The refactored example should give you valuable hints on how to work around mocking static calls. If there is still the need to mock them, you don't need to include PowerMock, as Mockito now supports it.

Are you looking for further practical resources on Mockito? Consider enrolling in my Hands-On With Mockito Online Course to learn the ins and outs of the most popular mocking library for JVM applications.

You can find related Mockito articles here:

The source code for this Mockito example is available on GitHub.

Have fun mocking static method calls with Mockito,

Philip

>