BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Mockito 5 Supports Mocking Constructors, Static Methods and Final Classes out of the Box

Mockito 5 Supports Mocking Constructors, Static Methods and Final Classes out of the Box

Mockito, the mocking framework for Java unit tests, has released version 5.0.0, switching the default MockMaker interface to mockito-inline in order to better support future versions of the JDK and allows mocking of constructors, static methods and final classes out of the box. The baseline increased from Java 8 to Java 11, as supporting both versions became costly, and managing changes in the JDK, such as the SecurityManager, proved difficult.

Before this release, Mockito didn't support mocking final classes out of the box, such as the following final class which contains one method:

public final class Answer {

    public String retrieveAnswer() {
        return "The answer is 2";
    }
}

In the unit test, a stub is used to replace the answer of the retrieveAnswer() method:

@Test
void testMockito() {
    Answer mockedAnswer = mock();
    String answer = "42 is the Answer to the Ultimate Question of Life, 
        the Universe, and Everything";
    when(mockedAnswer.retrieveAnswer()).thenReturn(answer);
    assertEquals(answer, mockedAnswer.retrieveAnswer());
}

Running the test displays the following exception:

org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class com.app.Answer
Mockito cannot mock/spy because :
 - final class

Mockito could mock final classes by supplying the mockito-inline dependency. However, starting with Mockito 5.0.0, the inline MockMaker is used by default and supports mocking of constructors, static methods and final classes. The subclass MockMaker is still available via the new mockito-subclass artifact, which is necessary on the Graal VM native image as the inline mocker doesn't work.

The ArgumentMatcher interface allows the creation of a custom matcher which is used as method arguments for detailed matches. The ArgumentMatcher now supports varargs, with one argument, via the type() method. For example, in order to mock the following method with a varargs argument:

public class Answer {
    public int count(String... arguments) {
        return arguments.length;
    }
}

It was always possible to match zero arguments or two or more arguments:

when(mockedAnswer.count()).thenReturn(2);
when(mockedAnswer.count(any(), any())).thenReturn(2);

The mock might also use one any() method as argument:

Answer mockedAnswer = mock();
when(mockedAnswer.count(any())).thenReturn(2);

However, before Mockito 5, the any() method would match any number of arguments, instead of one argument. The mock above would match with the following method invocations:

mockedAnswer.count()
mockedAnswer.count("one")
mockedAnswer.count("one", "two")

Mockito 5 allows to match exactly one varargs argument with:

when(mockedAnswer.count(any())).thenReturn(2);

Alternatively, Mockito 5 allows matching any number of arguments:

when(mockedAnswer.count(any(String[].class))).thenReturn(2);

Mockito 5 may be used after adding the following Maven dependency:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.0.0</version>
    <scope>test</scope>
</dependency>

Alternatively, the following Gradle dependency may be used:

testImplementation 'org.mockito:mockito-core:5.0.0'

More information about Mockito 5.0.0 can be found in the detailed explanations inside the release notes on GitHub.

About the Author

Rate this Article

Adoption
Style

BT