关于Java:如何在JUnit5中使用Mockito

How to use Mockito with JUnit5

如何在Mockito和JUnit 5中使用注入?

在JUnit4中,我只能使用@RunWith(MockitoJUnitRunner.class)注释。在JUnit5中是否没有@RunWith批注?


有多种使用Mockito的方法-我将一一介绍。

手动地

使用Mockito::mock手动创建模拟程序的工作与JUnit版本(或与此相关的测试框架)无关。

基于注释

使用@Mock注释和对MockitoAnnotations::initMocks的相应调用
无论JUnit版本是什么(无论是测试框架还是Java的测试框架,Java 9都可能在此干扰,这取决于测试代码是否在模块中),创建模拟程序的工作原理。

Mockito扩展

JUnit 5具有强大的扩展模型,Mockito最近在组/工件ID org.mockito下发布了一个模型:mockito-junit-jupiter。

您可以通过将@ExtendWith(MockitoExtension.class)添加到测试类并使用@Mock注释模拟字段来应用扩展。从MockitoExtension的JavaDoc:

1
2
3
4
5
6
7
8
9
10
11
12
@ExtendWith(MockitoExtension.class)
public class ExampleTest {

    @Mock
    private List list;

    @Test
    public void shouldDoSomething() {
        list.add(100);
    }

}

MockitoExtension文档描述了实例化模拟的其他方法,例如,使用构造函数注入(如果您在测试类中对最终字段进行了rpefer)。

没有规则,没有赛跑者

JUnit 4规则和运行器在JUnit 5中不起作用,因此不能使用MockitoRule和Mockito运行器。


使用Mockito的MockitoExtension。该扩展包含在新的工件mockito-junit-jupiter

1
2
3
4
5
6
<dependency>
    <groupId>org.mockito</groupId>
    mockito-junit-jupiter</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>

它使您可以像使用JUnit 4一样编写测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

    ...
}


有许多不同的方法可以做,但是更简洁的方法也符合JUnit 5的理念,它为Mockito创建了org.junit.jupiter.api.extension.Extension

1)手动创建模拟会失去其他Mockito检查的好处,以确保您正确使用框架。

2)在每个测试类中调用MockitoAnnotations.initMocks(this)是我们可以避免的样板代码。
并且在抽象类中进行此设置也不是一个好的解决方案。
它将每个测试类耦合到一个基类。
如果出于某种原因您需要一个新的基础测试类,则可以完成一个3级类层次结构。请避免那样。

3)测试规则是JUnit 4的特异性。
甚至不用考虑。
并且文档很清楚:

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实际上不是扩展JUnit 5框架的方法。
通过使用JUnit 5扩展,JUnit 5提供了用于编写测试的扩展模型,从而简化了JUnit 4 Runners的工作。
甚至不用考虑。

因此,欢迎使用org.junit.jupiter.api.extension.Extension方式。

编辑:实际上,Mockito捆绑了木星扩展名:mockito-junit-jupiter

然后,非常简单易用:

1
2
3
4
5
6
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class FooTest {
     ...    
}

这是乔纳森(Jonathan)出色回答的补充。

通过添加mockito-junit-jupiter工件作为依赖项,使用@ExtendWith(MockitoExtension.class)会在执行测试时产生以下异常:

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

问题是mockito-junit-jupiter依赖于两个独立的库。
例如对于mockito-junit-jupiter:2.19.0

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
  <groupId>org.mockito</groupId>
  mockito-core</artifactId>
  <version>2.19.0</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  junit-jupiter-api</artifactId>
  <version>5.1.0</version>
  <scope>runtime</scope>
</dependency>

问题是我使用了junit-jupiter-api:5.0.1

因此,由于junit-jupiter-api在API方面仍然经常移动,请确保您依赖mockito-junit-jupiter所依赖的相同版本的junit-jupiter-api


您必须使用新的@ExtendWith注释。

很遗憾,还没有发行版本。
在github上,您可以看到该扩展的beta实现。作为示例演示测试。