Contents

Mock constructor calls with Mockito 5

Writen by: David Vlijmincx

Using Mockito 4?

The example code in this post only works with Mockito 5 and Java 11 or higher. If you are using an older version, please see this post about mocking constructor calls with Mockito 4.

Introduction

For some test cases, it can be helpful to mock a call to a constructor. In earlier versions of Mockito, you had to enable the mockmaker-inline to do so. Now with Mockito 5, the mockmaker-inline is the new default, replacing the subclass-mockmaker used as the default in Mockito 4.

With the mockmaker-inline enabled by default mocking constructors is even easier with Mockito 5. In this short post, I will show you how to mock a constructor inside a @test annotated method using Mockito 5.

Maven Dependency

For the examples, I used version 5.0.0 of Mockito. With Mockito 5 you no longer need to include the “mockito-inline” artifact or create “org.mockito.plugins.MockMaker” file to enable the mockmaker-inline as it is enabled by default.

1
2
3
4
5
6
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.0.0</version>
    <scope>test</scope>
</dependency>

Mocking constructors

With the mockConstruction you can mock calls made to the constructor. In the following example, we mock the constructor call made to the class Car. Mocking a constructor is done inside a try-with-resources statement. Inside the try-with-resources statement, a mock will be returned every time the constructor is called. Outside the try-with-resources statement, the constructor won't be mocked and the real constructor will be called giving you a real instance of the Car class.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Car {
    public Car() {}
    public String GetSpeedAsString() {return "60";}
}

@Test
void mockingConstructor() {

    // Scope of constructor mocking
    try (MockedConstruction<Car> mock = mockConstruction(Car.class)) {
        // creating a mock instance
        Car car = new Car();
        when(car.GetSpeedAsString()).thenReturn("120");

        assertEquals("120", car.GetSpeedAsString());

        // Get a list of all created mocks
        List<Car> constructed = mock.constructed();
        assertEquals(1, constructed.size());
    }

    // Normal Car instance that is not mocked
    assertEquals("60", new Car().GetSpeedAsString());
}

This example also works when you mock a private constructor. If the Car class had a private constructor, the testing code would still succeed.

Mock constructor inside another class

We can also mock a constructor when it is called inside another class. In the following example, we have the class Owner and Car. Inside the constructor of the Owner, we create an instance of Car and set the model to “Audi”.

In the following example, we mock the constructor of the Car class inside a try-with-resources statement. Every time we call the constructor of the Car class a mock will be returned. When a new Owner instance is created on line 4, a mock object of Car is also created. We use mock.constructed().get(0) to get the firstly created mocked instance of Car. We can use this instance to verify calls, stubbing, and more.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@Test
void testObjectCreation(){
    try (MockedConstruction<Car> mock = mockConstruction(Car.class)) {
    Owner owner = new Owner();

    // Get the first mock
    Car mockCar = mock.constructed().get(0);

    verify(mockCar).setModel("Audi");
    }
}

class Owner{

    public Owner() {
        Car car = new Car();
        car.setModel("Audi");
    }

}

Change default mock behavior

Methods we don't stub of a mock return null by default. We can take the examples one step further and let the mock behave like a real Car instance. The MockedConstruction is again inside a try with resources, but this time we pass it an extra parameter. When we pass withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS) to the MockedConstruction we tell it to create a mock that will behave like a real Car instance for methods that we didn't stub.

1
2
3
4
5
6
7
@Test
void defaultMethods(){
    try (MockedConstruction<Car> mock = mockConstruction(Car.class, withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS))) {
        Car Car = new Car();
        System.out.println(Car.GetSpeedAsString());
    }
}

By default, this would print null to the console, but now it prints 60.

Conclusion

This post showed how we mock calls made to a constructor using Mockito 5.

If you are curious and want to know more about what you can do with Mockito, please check out their documentation https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html. It lists all the Mockito features and how to use them.

Further reading

More about testing in Java: