我正在尝试使用 Mockito 为 Quarkus 编写单元测试,但我无法模拟事物。
这是一个最小的(不是)工作示例:
package com.my.package;
import io.quarkus.test.junit.QuarkusTest;
import org.mockito.Mockito;
import org.mockito.Mock;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@QuarkusTest
public class LoadCalculatorServiceTest {
public class Foobar {
public int baz;
public void setBaz(int baz) {
this.baz = baz;
}
public int getBaz() {
return this.baz;
}
}
@Mock
Foobar foobar;
// Foobar foobar = new Foobar(); // doesn’t work either
@Test
public void myTest() {
Mockito.when(foobar.getBaz()).thenReturn(4); // NullPointer
Assertions.assertEquals(4,foobar.getBaz());
}
}
测试在 NullPointer 上崩溃。
我读到这些问题可以通过用
@RunWith(MockitoJUnitRunner.class)
、@ExtendWith(MockitoExtension.class)
注释测试来解决(出于某种原因,我期望 @QuarkusTest
无论如何都会这样做?),但是我找不到正确的导入来加载它们。
我尝试了
org.junit.jupiter.api.MockitoExtension
、org.junit.runner.RunWith
和各种变体,但没有成功。
这是我的
pom.xml
的相关部分:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-mockito</artifactId>
<scope>test</scope>
</dependency>
我错过了什么?
我想原始代码适用于简单风格的模拟:
Foobar foobar = Mockito.mock(Foobar.class);
所以问题实际上是如何使
@Mock
注释起作用?为此需要几件事:
JUnit5 中的
@RunWith
注释已被 @ExtendWith
替换(或者我们应该说 升级)。可以使用
import org.junit.jupiter.api.extension.ExtendWith;
将其导入到 Quarkus 中。
@RunWith
通常用作@ExtendWith(MockitoExtension.class)
。可以使用 import org.mockito.junit.jupiter.MockitoExtension;
将 MockitoExtension 导入到 Quarkus 中。 注意,mockito-junit-jupiter
依赖项(来自org.mockito
组)必须添加到pom.xml
,因为quarkus-junit5-mockito
包不依赖于它。
模拟必须在测试之前由
MockitoAnnotations.initMocks()
初始化。请注意,虽然使用 @BeforeAll
作为设置函数似乎更有意义,但显然这不是此注释的重点,应该使用 @BeforeEach
(前者需要设置是静态的,而 IIUC 需要设置无论如何,函数将在每次测试之前调用)。
最后
@Mock
注释应该可以工作。
总而言之,原始代码将变为:
package com.my.package;
import io.quarkus.test.junit.QuarkusTest;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@QuarkusTest
@ExtendWith(MockitoExtension.class)
public class LoadCalculatorServiceTest {
public class Foobar {
public int baz;
public void setBaz(int baz) {
this.baz = baz;
}
public int getBaz() {
return this.baz;
}
}
@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Mock
Foobar foobar;
@Test
public void myTest() {
Mockito.when(foobar.getBaz()).thenReturn(4);
Assertions.assertEquals(4,foobar.getBaz());
}
}
对
pom.xml
添加以下内容:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
我正在使用quarkus 1.8.1.Final,使用mockito 3.6.0,我对@Mock注释有同样的问题,我遵循了Skippy le Grand Gourou的答案,但它不起作用,所以我删除了@QuarkusTest注解,并删除de MockitoAnnotations.initMocks(this)方法,我的mockito版本已经弃用了这个,然后用@Mock注解运行测试。我是 Quarkus 的新手,所以我不太清楚删除 @QuarkusTest 的副作用
当您使用
MockitoExtension
扩展它时,不需要 @QuarkusTest
的存在。只需在代码中包含 @ExtendWith(MockitoExtension.class)
并排除 @QuarkusTest
就可以了。
但是,如果您打算保留
@QuarkusTest
,则必须使用 Quarkus 的 @InjectMock 来实现此目的。 @InjectMock
有助于创建 Mockito 模拟。因此,修改后的代码如下所示:
@QuarkusTest
public class LoadCalculatorServiceTest {
@ApplicationScoped
static class Foobar {
public int baz;
public void setBaz(int baz) {
this.baz = baz;
}
public int getBaz() {
return this.baz;
}
}
@InjectMock
Foobar foobar;
@Test
public void myTest() {
when(foobar.getBaz()).thenReturn(4); // NullPointer
Assertions.assertEquals(4,foobar.getBaz());
}
}