如何使用 Mockito 和 JUnit 5 进行注入?
在 JUnit 4 中,我可以只使用
@RunWith(MockitoJUnitRunner.class)
注释。@RunWith
注解。
使用 Mockito 有多种不同的方法 - 我将一一介绍。
Mockito::mock
手动创建模拟都可以工作。
使用 @Mock 注释和相应的调用
MockitoAnnotations::initMocks
无论 JUnit 版本如何(或测试框架,但 Java 9 可能会干扰这里,具体取决于测试代码是否最终出现在模块中),创建模拟都可以工作。
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 运行程序。
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
...
}
有不同的方法可以实现,但更简洁且尊重 JUnit 5 理念的方法是为 Mockito 创建一个
org.junit.jupiter.api.extension.Extension
。
1) 手动创建模拟会失去额外的 Mockito 检查的好处,以确保您正确使用框架。
2)在每个测试类中调用
MockitoAnnotations.initMocks(this)
是我们可以避免的样板代码。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
。
对于 Kotlin 以及注释字段时,请确保用
lateinit
: 进行标记
@ExtendWith(MockitoExtension.class)
class MyTest {
@Mock
lateinit var list: List
@Test
fun `Test should work`() {
list.add(100)
}
}