无法在 Quarkus 中进行模拟,出现了 NullPointer 异常,并且找不到相关的导入。

huangapple go评论65阅读模式
英文:

Unable to mock with Quarkus, NullPointer exception and cannot find relevant imports

问题

我正在尝试使用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(); // 也不起作用

    @Test
    public void myTest() {
        Mockito.when(foobar.getBaz()).thenReturn(4); // 空指针异常
        Assertions.assertEquals(4, foobar.getBaz());
    }
}

测试在空指针异常上崩溃。

我阅读到这种问题可以通过在测试上加注解@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>

我错过了什么?

英文:

I am trying to write unit tests for Quarkus using Mockito, but I fail mocking things.

Here is a minimal (not) working example :

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());
    }
}

The test crashes on a NullPointer.

I read such issues may be fixed by annotating the test with @RunWith(MockitoJUnitRunner.class), @ExtendWith(MockitoExtension.class) (which for some reason I expected @QuarkusTest to do anyway ?), however I fail to find the correct imports to load them.

I tried org.junit.jupiter.api.MockitoExtension, org.junit.runner.RunWith and variations, without success.

Here is the relevant part of my pom.xml :

    &lt;dependency&gt;
      &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
      &lt;artifactId&gt;quarkus-junit5&lt;/artifactId&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
      &lt;artifactId&gt;quarkus-junit5-mockito&lt;/artifactId&gt;
      &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;

What am I missing ?

答案1

得分: 6

我发现原始代码使用普通样式的模拟工作

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

所以实际的问题是如何使@Mock注解起作用?为此需要几个步骤:

  1. @RunWith注解已经被JUnit5中的@ExtendWith注解替代(或者我们可以说是升级)。在Quarkus中,可以使用import org.junit.jupiter.api.extension.ExtendWith;导入。

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

  3. 必须在测试之前通过MockitoAnnotations.initMocks()初始化模拟。请注意,尽管使用@BeforeAll作为设置函数似乎更合理,但显然这不是此注解的用途,应该使用@BeforeEach(前者需要设置为静态,并且据我所知,设置函数将在每个测试之前调用)。

  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>
英文:

I figured the original code works with plain-style mocks :

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

So the question is actually how to make the @Mock annotation work ? There are several things needed for that :

  1. The @RunWith annotation has been replaced (or should we say upgraded) by @ExtendWith in JUnit5. It can be imported in Quarkus using import org.junit.jupiter.api.extension.ExtendWith;.

  2. @RunWith is usually used as @ExtendWith(MockitoExtension.class). MockitoExtension can be imported in Quarkus using import org.mockito.junit.jupiter.MockitoExtension;. Beware that the mockito-junit-jupiter dependency (from the org.mockito group) must be added to the pom.xml, since the quarkus-junit5-mockito packages do not depend on it.

  3. Mocks have to be initialized by MockitoAnnotations.initMocks() before the tests. Note that although it may seem to make more sense to use @BeforeAll for the setup function, apparently it is not the point of this annotation and one should use @BeforeEach (the former needs the setup to be static, and IIUC the setup function will be called before each test anyway).

  4. Then finally the @Mock annotation should work.

To summarize, the original code would become :

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());
    }
}

with the following addition to the pom.xml :

&lt;dependency&gt;
  &lt;groupId&gt;org.mockito&lt;/groupId&gt;
  &lt;artifactId&gt;mockito-junit-jupiter&lt;/artifactId&gt;
  &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

答案2

得分: 0

我正在使用Quarkus 1.8.1.Final,以及Mockito 3.6.0。我在使用@Mock注解时遇到了相同的问题,然后我按照Skippy le Grand Gourou的回答进行了操作,但没有成功。因此,我删除了@QuarkusTest注解,并且删除了MockitoAnnotations.initMocks(this)方法。我的Mockito版本已经弃用了这个方法,然后测试使用@Mock注解运行起来了。我刚开始使用Quarkus,所以我不太清楚移除@QuarkusTest注解会有什么副作用。

英文:

I'm using quarkus 1.8.1.Final, with mockito 3.6.0, I had the same issue with @Mock annotation and I followed the answer from Skippy le Grand Gourou and it didn't work, so I deleted the @QuarkusTest annotation, and delete de MockitoAnnotations.initMocks(this) method, my mockito version has deprecated this, then the test run with the @Mock annotation. I'm new doing Quarkus so I don't know very well the side effects of removing @QuarkusTest

huangapple
  • 本文由 发表于 2020年9月23日 23:59:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/64031910.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定