首页 > 解决方案 > 无法使用 Quarkus 模拟,NullPointer 异常并且找不到相关导入

问题描述

我正在尝试使用 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.MockitoExtensionorg.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>

我错过了什么?

标签: javaunit-testingjunitmockitoquarkus

解决方案


我认为原始代码适用于普通样式的模拟:

Foobar foobar = Mockito.mock(Foobar.class);

所以问题实际上是如何使@Mock注释起作用? 为此需要做几件事:

  1. 在 JUnit5 中,@RunWith注释已被替换(或者我们应该说升级) 。@ExtendWith它可以在 Quarkus 中使用import org.junit.jupiter.api.extension.ExtendWith;.

  2. @RunWith通常用作@ExtendWith(MockitoExtension.class). MockitoExtension 可以使用import org.mockito.junit.jupiter.MockitoExtension;. 请注意,必须将mockito-junit-jupiter依赖项(来自org.mockito组)添加到pom.xml,因为quarkus-junit5-mockito不依赖于它

  3. 模拟必须MockitoAnnotations.initMocks()在测试之前初始化。请注意,虽然使用 setup 函数似乎更有意义@BeforeAll,但显然这不是此注释的重点,应该使用@BeforeEach(前者需要 setup 是静态的,IIUC setup 函数将在每个之前调用无论如何都要测试)。

  4. 然后最后@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>

推荐阅读