如何将 Mockito 与 JUnit 5 结合使用?

问题描述 投票:0回答:5

如何使用 Mockito 和 JUnit 5 进行注入?

在 JUnit 4 中,我可以只使用

@RunWith(MockitoJUnitRunner.class)
注释。
在 JUnit 5 中,没有
@RunWith
注解。

java unit-testing junit mockito junit5
5个回答
313
投票

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

手动

无论 JUnit 版本(或测试框架)如何,使用

Mockito::mock
手动创建模拟都可以工作。

基于注释

使用 @Mock 注释和相应的调用

MockitoAnnotations::initMocks
无论 JUnit 版本如何(或测试框架,但 Java 9 可能会干扰这里,具体取决于测试代码是否最终出现在模块中),创建模拟都可以工作。

Mockito 扩展

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

您可以通过将

@ExtendWith(MockitoExtension.class)
添加到测试类并使用
@Mock
注释模拟字段来应用扩展。来自
MockitoExtension
的 JavaDoc:

@ExtendWith(MockitoExtension.class)
public class ExampleTest {

    @Mock
    private List list;

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

}

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

没有规则,就没有跑步者

JUnit 4 规则和运行程序在 JUnit 5 中不起作用,因此无法使用

MockitoRule
Mockito 运行程序


86
投票

使用 Mockito 的

MockitoExtension
。该扩展包含在一个新工件中
mockito-junit-jupiter
:

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

它允许您像使用 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

    ...
}

13
投票

有不同的方法可以实现,但更简洁且尊重 JUnit 5 理念的方法是为 Mockito 创建一个

org.junit.jupiter.api.extension.Extension

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

2)在每个测试类中调用

MockitoAnnotations.initMocks(this)
是我们可以避免的样板代码。
在抽象类中进行此设置也不是一个好的解决方案。
它将每个测试类耦合到基类。
如果您有充分的理由需要一个新的基测试类,那么您可以使用 3 级类层次结构来完成。请避免这样做。

3) 测试规则是 JUnit 4 的特殊性。
想都别想。
文档对此很清楚:

但是,如果您打算为 JUnit 5 开发新的扩展,请 使用 JUnit Jupiter 的新扩展模型而不是基于规则的 JUnit 4 的模型。

4) Test Runner 实际上不是扩展 JUnit 5 框架的方法。
由于 JUnit 5 扩展,JUnit 5 提供了用于编写测试的扩展模型,从而简化了 JUnit 4 运行者的困境。
想都别想。

所以赞成

org.junit.jupiter.api.extension.Extension
方式。


编辑:实际上,Mockito 捆绑了一个 jupiter 扩展:

mockito-junit-jupiter

然后,使用起来非常简单:

import org.mockito.junit.jupiter.MockitoExtension;

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

这是对乔纳森出色答案的补充。

通过添加

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
:

<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>

问题是我使用了

junit-jupiter-api:5.0.1

由于

junit-jupiter-api
在 API 方面仍然经常变化,请确保您依赖于
junit-jupiter-api
所依赖的相同版本的
mockito-junit-jupiter


4
投票

您必须使用新的

@ExtendWith
注释。

不幸的是,目前还没有发布任何扩展。 在 github 上,您可以看到该扩展的测试版实现。作为示例演示测试


0
投票

对于 Kotlin 以及注释字段时,请确保用

lateinit
:

进行标记
@ExtendWith(MockitoExtension.class)
class MyTest {
    @Mock
    lateinit var list: List

    @Test
    fun `Test should work`() {
        list.add(100)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.