How to use Mockito with JUnit5 How to use Mockito with JUnit5 java java

How to use Mockito with JUnit5


There are different ways to use Mockito - I'll go through them one by one.

Manually

Creating mocks manually with Mockito::mock works regardless of the JUnit version (or test framework for that matter).

Annotation Based

Using the @Mock-annotation and the corresponding call to MockitoAnnotations::initMocks to create mocks works regardless of the JUnit version (or test framework for that matter but Java 9 could interfere here, depending on whether the test code ends up in a module or not).

Mockito Extension

JUnit 5 has a powerful extension model and Mockito recently published one under the group / artifact ID org.mockito : mockito-junit-jupiter.

You can apply the extension by adding @ExtendWith(MockitoExtension.class) to the test class and annotating mocked fields with @Mock. From MockitoExtension's JavaDoc:

@ExtendWith(MockitoExtension.class)public class ExampleTest {    @Mock    private List list;    @Test    public void shouldDoSomething() {        list.add(100);    }}

The MockitoExtension documentation describes other ways to instantiate mocks, for example with constructor injection (if you rpefer final fields in test classes).

No Rules, No Runners

JUnit 4 rules and runners don't work in JUnit 5, so the MockitoRule and the Mockito runner can not be used.


Use Mockito's MockitoExtension. The extension is contained in a new artifact mockito-junit-jupiter:

<dependency>    <groupId>org.mockito</groupId>    <artifactId>mockito-junit-jupiter</artifactId>    <version>2.23.4</version>    <scope>test</scope></dependency>

It allows you to write tests as you would have with JUnit 4:

import org.mockito.junit.jupiter.MockitoExtension;import org.junit.jupiter.api.extension.ExtendWith;import org.mockito.InjectMocks;import org.mockito.Mock;@ExtendWith(MockitoExtension.class)class MyTest {    @Mock    private Foo foo;    @InjectMocks    private Bar bar; // constructor injection    ...}


There are different ways to do but the cleaner way and that also respects the JUnit 5 philosophy is creating a org.junit.jupiter.api.extension.Extension for Mockito.

1) Creating mocks manually makes lose the benefit of additional Mockito checks to ensure you use correctly the framework.

2) Calling MockitoAnnotations.initMocks(this) in every test classes is boiler plate code that we could avoid.
And making this setup in an abstract class is not a good solution either.
It couples every test classes to a base class.
If then you need a new base test class for good reasons, you finish with a 3- level class hierarchy. Please avoid that.

3) Test Rules is a JUnit 4 specificity.
Don't even think of that.
And the documentation is clear about that :

However, if you intend to develop a new extension for JUnit 5 please use the new extension model of JUnit Jupiter instead of the rule-based model of JUnit 4.

4) Test Runner is really not the way to extend the JUnit 5 framework.
JUnit 5 simplified the hell of the Runners of JUnit 4 by providing an extension model for writing tests thanks to JUnit 5 Extensions.
Don't even think of that.

So favor the org.junit.jupiter.api.extension.Extension way.


EDIT : Actually, Mockito bundles a jupiter extension : mockito-junit-jupiter

Then, very simple to use :

import org.mockito.junit.jupiter.MockitoExtension;@ExtendWith(MockitoExtension.class)public class FooTest {     ...    }

Here is an addition to the excellent answer of Jonathan.

By adding as dependency the mockito-junit-jupiter artifact, the use of @ExtendWith(MockitoExtension.class) produced the following exception as the test is executed :

java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation(Ljava/util/Optional;Ljava/lang/Class;)Ljava/util/Optional;

THe problem is that mockito-junit-jupiter depends on two independent libraries. For example for mockito-junit-jupiter:2.19.0 :

<dependency>  <groupId>org.mockito</groupId>  <artifactId>mockito-core</artifactId>  <version>2.19.0</version>  <scope>compile</scope></dependency><dependency>  <groupId>org.junit.jupiter</groupId>  <artifactId>junit-jupiter-api</artifactId>  <version>5.1.0</version>  <scope>runtime</scope></dependency>

The problem was I used junit-jupiter-api:5.0.1.

So as junit-jupiter-api moves still often in terms of API, make sure you depend on the same version of junit-jupiter-api that mockito-junit-jupiter depends on.