Mock Java Constructors With Mockito | Configuration and Examples

Last Updated:  August 27, 2021 | Published: January 19, 2021

Starting with Mockito version 3.5.0, we can now mock Java constructors with Mockito. This allows us to return a mock from every object construction for testing purposes. Similar to mocking static method calls with Mockito, we can define the scope of when to return a mock from a Java constructor for a particular Java class. While the practical (and reasonable) use cases for this feature might be limited, at least it's the next step towards replacing PowerMock with Mockito entirely. Let's take a look at this feature in action.

Configuration of the Mockito InlineMockMaker

This new feature of Mockito is only available if we use an InlineMockMaker. The InlineMockMaker is an interface that extends the MockMaker interface that defines Mockito's internal API to create mocks. There are multiple implementations for this interface, and the default one is the SubclassByteBuddyMockMaker.

To override the default MockMaker and use a InlineMockMaker instead, we can replace our mockito-core dependency with mockito-inline :

If, for some reason, we are not able to add this dependency to our project and only rely on mockito-core, we can still configure the InMockMaker with an extension file.

Therefore, put a org.mockito.plugins.MockMaker file inside src/test/resources/mockito-extensions with the following content:

For those using the Spring Boot Starter Test to manage the versions of the basic testing libraries, refer to the Mockito setup section of this article.

Mocking a Java Constructor With Mockito

Let's see how we can mock the construction of an object with Mockito. As an example, we'll use the following Java class:

Furthermore, let's assume an instance of this PaymentProcess is created manually inside the CheckoutService using the new operator.

If we used constructor/field/setter injection instead, this Mockito feature wouldn't be relevant. In such cases, we can pass the mocked version of a collaborator and don't have to mock the constructor.

When writing a unit test for the purchaseProduct method, we want to mock collaborators of our class under test. For this purpose, we can now use the new feature of Mockito and mock the object construction of the PaymentProcessor inside purchaseProduct.

The new method that makes mocking object constructions possible is Mockito.mockConstruction(). This method takes a non-abstract Java class that constructions we're about to mock as a first argument. In the example above, we use an overloaded version of mockConstruction() to pass a MockInitializer as a second argument. This MockInitializer is a callback that we use to stub the behavior of the mock.

We can define the scope of mocking any object creation for our PaymentProcessor by using Java's try-with-resources construct, as the MockedConstruction is extending the AutoClosable interface. This allows mocking the object construction only for a temporary and user-defined purpose.

If you've already mocked a static method with Mockito, this setup might seem familiar.

Let's take a look at further examples of how we can use this new feature of Mockito.

Further Examples to Mock Java Constructors with Mockito

First, let's come back to the scope of mocking the object construction. Whenever we use the try-with-resources (highly recommended for this use case) construct, every constructor call inside this block is mocked. Any object creation before or after returns a real instance:

Furthermore, as all object constructions for this class are mocked, it doesn't matter which public constructor we use:

In the test above, all object creations are mocked, independent of which constructor of PaymentProcessor we use. We can even inspect how many mock objects were created during a test using the mock controller that is returned from mockConstruction().

As the last example, let's take a look at mockConstructionWithAnswer. Using this method, we can add a default Answer and additional Answers that define our mock's behavior.

In our example, we can always return a BigDecimal as our PaymentProcessor only has one public method. For classes with multiple methods and different return types, either use the passed invocation to determine what to return or use the mockConstruction() that takes a MockInitializer for type-safe stubbings.

Summary of Mocking Java Constructors

As we can now mock Java constructors and static method calls with Mockito, the need for PowerMock becomes less important. With this feature, you can get rid of PowerMock if you've only used it for those two purposes and rely solely on Mockito.

However, we shouldn't jump into using this feature from now on for every test. Mocking the object construction, e.g., of internally used value objects, is an anti-pattern which we should avoid.

There shouldn't be many valid use cases for this feature whenever we favor constructor injection for our Java classes. With constructor injection, we can pass the collaborators of a class via the constructor during tests. This way, we can prepare a mock of the collaborator before instantiating the class under test and don't have to mock any constructor.

For further practical Mockito advice, consider enrolling in the Hands-On Mocking With Mockito Online Course to learn the ins and outs of the most popular mocking library for JVM applications.

You can find the source code for this blog post on GitHub.

Have fun mocking your Java constructors,

Philip

    • Hi Daniel,

      you can use the .constructed() method MockedConstruction mocked to retrieve a list of mocked objects that were created using the constructor. You can check the length of this list to verify that the constructor returned a mock (once or multiple times).

      I’m not aware that you can somehow use Mockito’s verify() for advanced verifications for the constructor.

      Kind regards,
      Philip

  • I tried to mock FileInputStream that’s called internally from another class but I got
    org.mockito.exceptions.base.MockitoException: Could not initialize mocked construction
    at java.io.FileInputStream.(FileInputStream.java)

    I posted full details on StackOverflow
    https://stackoverflow.com/q/68908833/3972599
    Can you please check it?

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

    Join Our Mailing List To Get 3x Free Cheat Sheets

    Free Java Cheat Sheets
    >