Contents

How to use the Mockito's inline mock maker

Introduction

Below you will find five ways of using Mockito that will help you write better tests. We are going to find out how to mock a constructor, mock static methods, have stricter mocking rules, mock final methods and classes, and how to use verify with argument captors.

Maven Dependency

For the examples, I used version 4.2.0 of Mockito.

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

We also need Mock maker inline to mock constructors, final and static methods. To enable it, you either add this dependency or create the file org.mockito.plugins.MockMaker.

Option 1: Mock maker inline dependency

Add this dependency in your pom.

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

Option 2: Adding a file to enable the Mock maker inline

Create a resources directory in your test directory if you do not have one. In resources create the directory mockito-extensions and in that directory the file org.mockito.plugins.MockMaker. The complete path should look like this: src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker.

In the file, add the following line mock-maker-inline. Now the mock maker inline is available to use.

Mocking constructors

With the mockConstruction you can mock calls made to the constructor. For example, we mock the constructor for the class Dog when your code calls the constructor, it returns a mock object. Keep this code in a try with resources to limit the scope, so you only mock the constructor in that test method.

If the method that you are testing calls the constructor of a class, that you want to mock, you don't have direct access to change its mocking behavior. To get a reference of the created mock, you can call the constructed() method on the MockedConstruction instance. It returns a list of all the created mock objects. The example below uses it to see how often the constructor is called.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Dog {
    public Dog() {}
    public String makeSound() {return "Woof";}
}

    @Test
    void mockingConstructor() {

        try (MockedConstruction<Dog> mock = mockConstruction(Dog.class)) {
            Dog dog = new Dog();
            when(dog.makeSound()).thenReturn("Bark");

            assertThat(dog.makeSound()).isEqualTo("Bark");

            List<Dog> constructed = mock.constructed();
            assertThat(constructed).hasSize(1);
        }
        assertThat(new Dog().makeSound()).isEqualTo("Woof");

    }

Mocking Static methods

With the inline mock maker, it's possible to mock static methods. The example shows how to mock the static method Instant.now(). Every call made to it will return a mock of Instant. Use a try with resources to limit the scope of the static method mocking to its test method.

I also included a version that uses LocalDateTime, because I often want to mock one of these classes without changing production code or using PowerMock.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Test
void mockingStaticMethods() {

        try (MockedStatic<Instant> mocked = mockStatic(Instant.class)) {
        var mockInstant = mock(Instant.class);
        when(mockInstant.getEpochSecond()).thenReturn(0l);
        mocked.when(Instant::now).thenReturn(mockInstant);

        var result = Instant.now();

        assertThat(result.getEpochSecond()).isEqualTo(0);
        }

        try (MockedStatic<LocalDateTime> mocked = mockStatic(LocalDateTime.class)) {
        var mockLocalDateTime = mock(LocalDateTime.class);
        when(mockLocalDateTime.getMinute()).thenReturn(30);
        mocked.when(LocalDateTime::now).thenReturn(mockLocalDateTime);

        var result = LocalDateTime.now();

        assertThat(result.getMinute()).isEqualTo(30);
        }

        }

Use strict mocking

Mockito is a loose mocking framework by default which means that you are allowed to create Mocks that have no interaction. Making Mockito stricter forces you to be explicit about what you want to test, or the test will fail. Setting the Strictness to STRICT_STUBS will result in higher quality and cleaner tests.

Below is an example of how we can achieve this. The code is run before and after each test so that mockito can tell which test is invalid.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
MockitoSession mockito;

@BeforeEach
void setup() {
        mockito = Mockito.mockitoSession()
        .strictness(Strictness.STRICT_STUBS)
        .startMocking();
        }

@AfterEach
void tearDown() {
        mockito.finishMocking();
        }

Mocking final methods and classes

With the inline mock maker, you can mock final classes and methods. You can do this using mock(SomeClazz.class) like you would with every other object you want to mock. In the example, we see it is the same as with non-final classes and methods.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
final class Cat {
    final String makeSound() {return "Meow";}
}

    @Test
    void mockingFinalClasses() {
        Cat cat = mock(Cat.class);
        when(cat.makeSound()).thenReturn("purr");
        assertThat(cat.makeSound()).isEqualTo("purr");
    }

Combine verify with argument matchers

Normally you would use an instance of an ArgumentCaptor to verify the input of a mocked method. But that results in multiple lines of code that you need to maintain. While it could be worth it if you do a lot of assertions. There is an easier way for less complex cases. With argThat we create a custom matcher that is validated against the input of each method invocation.

1
2
3
4
5
6
7
@Test
void simpleArgumentMatchers() {
        List<String> list = (List<String>) mock(List.class);
        list.add("one");
        list.add("two");
        verify(list, times(2)).add(argThat(a -> a.contains("o")));
        }

If we mock a method that has multiple arguments, we need to add an extra argThat like this:

1
2
3
4
5
6
7
@Test
void simpleArgumentMatchersMultipleArguments() {
        Map<String, Integer> map = (Map<String,Integer>) mock(Map.class);
        map.put("one", 1);
        map.put("two", 2);
        verify(map, times(2)).put(argThat(a -> a.contains("o") ),argThat(a -> a < 3 ));
        }

Conclusion

I hope these few methods will help you write better tests, it helped me a lot to write higher-quality tests.

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:

Join the discussion: follow me on Twitter and share your thoughts

This post is just the beginning. If you're interested in learning more, be sure to follow me on Twitter . And if you have any questions or ideas, don't hesitate to reach out via Twitter or send me an email. I'm always happy to connect and continue the conversation.