在JUnit 4中,我可以使用
@RunWith(MockitoJUnitRunner.class)
注解。
在JUnit 5中,没有@RunWith
注解。@RunWith(MockitoJUnitRunner.class)
注解。
在JUnit 5中,没有@RunWith
注解。使用Mockito有不同的方法 - 我将逐一介绍它们。
使用Mockito::mock
手动创建模拟对象可以在任何JUnit版本(或测试框架)中运行。
使用@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文档描述了其他实例化mock的方法,例如使用构造函数注入(如果您喜欢在测试类中使用final字段)。
JUnit 4规则和运行器在JUnit 5中不起作用,因此MockitoRule
和Mockito运行器不能使用。
使用Mockito的MockitoExtension
。该扩展包含在新的artifact 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
...
}
@ExtendWith(MockitoExtension.class)
相当于 JUnit4 的 @RunWith(MockitoJUnitRunner.class)
。 - Sergey Nemchinov有不同的方法可供选择,但更清晰的方式并且也符合JUnit 5的理念是创建一个用于Mockito的org.junit.jupiter.api.extension.Extension
。
1) 手动创建mocks会失去额外的Mockito检查所带来的好处,以确保您正确使用该框架。
2) 在每个测试类中调用MockitoAnnotations.initMocks(this)
是样板代码,我们可以避免这种情况。
在抽象类中进行此设置也不是一个好的解决方案。
它将每个测试类与基类耦合在一起。
如果您需要一个新的基本测试类,那么您就会得到一个3级类层次结构。请避免这种情况。
3) 测试规则是JUnit 4的特定内容。
甚至不要想。
文档对此非常清楚:
然而,如果您打算为JUnit 5开发新扩展,请使用JUnit Jupiter的新扩展模型,而不是JUnit 4的基于规则的模型。
4) 测试运行器真的不是扩展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 {
...
}
这是对Jonathan优秀答案的补充。
通过添加依赖项mockito-junit-jupiter
artifact,使用@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 方面经常更新,请确保您依赖于与 mockito-junit-jupiter
相同版本的 junit-jupiter-api
。mockito-junit-jupiter
无法拉取正确版本的junit-jupiter-api
? - haelixmockito-junit-jupiter:2.19.0
。而JUnit Jupiter版本以 5
开头。mockito-junit-jupiter应该在其构件标识符中指定两个内容(Mockito版本和JUnit Jupiter版本),以使事情更清晰。例如,mockito-junit-jupiter-5.1:2.19.0
表示该库是为 JUnit Jupiter 5.1 设计的。 - davidxxxMockitoExtension
在 mockito-core
版本 3.0.0 中似乎不存在。 - Thunderforgemockito-junit-jupiter
中定义的。 - davidxxx@ExtendWith(MockitoExtension.class)
class MyTest {
@Mock
lateinit var list: List
@Test
fun `Test should work`() {
list.add(100)
}
}
@Test
注释的方法需要是公共的吗?还是“包私有”就足够了? - Geek