161

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

在 JUnit4 中,我可以只使用@RunWith(MockitoJUnitRunner.class)注解。在 JUnit5 中是没有@RunWithAnnotation 的吗?

4

4 回答 4

241

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

手动

Mockito::mock无论 JUnit 版本(或相关的测试框架)如何,都可以手动创建模拟。

基于注释

无论 JUnit 版本如何(或测试框架,但 Java 9 可能会在这里干扰,这取决于测试代码是否在模块中结束),使用@Mock -annotation 和相应的调用来MockitoAnnotations::initMocks 创建模拟都可以工作。

模拟扩展

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 中不起作用,因此不能使用MockitoRuleMockito 运行器。

于 2016-12-04T19:53:41.977 回答
78

使用 Mockito 的MockitoExtension. 扩展包含在一个新的工件中mockito-junit-jupiter

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>2.23.4</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

    ...
}
于 2018-04-04T16:17:20.347 回答
11

有不同的方法可以做,但更清洁的方法也尊重 JUnit 5 的理念是 org.junit.jupiter.api.extension.Extension为 Mockito 创建一个。

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

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

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

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

4) Test Runner 真的不是扩展 JUnit 5 框架的方法。
由于 JUnit 5 Extensions,JUnit 5 提供了一个用于编写测试的扩展模型,从而简化了 JUnit 4 的 Runners 地狱。
想都别想。

所以赞成的org.junit.jupiter.api.extension.Extension方式。


编辑:实际上,Mockito 捆绑了一个木星扩展: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-apimockito-junit-jupiter依赖的版本相同。

于 2017-12-27T17:54:08.177 回答
5

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

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

于 2016-12-04T16:50:52.417 回答