@Mock 注释后模拟实例为空

mock instance is null after @Mock annotation

我尝试运行这个测试:

    @Mock IRoutingObjHttpClient routingClientMock;
    @Mock IRoutingResponseRepository routingResponseRepositoryMock;


    @Test
    public void testSendRoutingRequest() throws Exception {
        CompleteRoutingResponse completeRoutingResponse = new CompleteRoutingResponse();
        completeRoutingResponse.regression_latencyMillis = 500L;

        Mockito.when(routingClientMock.sendRoutingRequest(any(RoutingRequest.class))).thenReturn(completeRoutingResponse);

        RoutingObjHttpClientWithReRun routingObjHttpClientWithReRun = new RoutingObjHttpClientWithReRun
                (routingClientMock, routingResponseRepositoryMock);

...
    }

但我得到了 NullPointerException:

Mockito.when(routingClientMock.

我错过了什么?

  1. 您应该在 class
  2. 处使用 @RunWith(SpringJUnit4ClassRunner.class)
  3. 您必须在@Before 方法中调用MockitoAnnotations.initMocks(this);

当您想使用 @Mock 注释时,您应该使用 MockitoJUnitRunner

@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {

    @Mock
    private IRoutingObjHttpClient routingClientMock;

    @Test
    public void testSendRoutingRequest() throws Exception {
        // ...
    }

}

另见 this tutorial

激活 @Mock 注解有三个选项:MockitoRule、MockitoJUnitRunner、MockitoAnnotations.initMocks(this)。恕我直言,使用 MockitoRule 是最好的,因为它仍然可以让您选择另一个跑步者,例如Parameterized.

使用MockitoRule

public class MockitoTest {

  @Mock
  private IRoutingObjHttpClient routingClientMock;

  @Rule
  public MockitoRule rule = MockitoJUnit.rule();

  @Test
  public void testSendRoutingRequest() throws Exception {
    // ...
  }
}

使用MockitoJUnitRunner

@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {

  @Mock
  private IRoutingObjHttpClient routingClientMock;

  @Test
  public void testSendRoutingRequest() throws Exception {
    // ...
  }
}

明确调用 MockitoAnnotations.initMocks(this)

这可以在 qn @Before 方法中、在您自己的运行程序中或在自己的规则中完成。

public class MockitoTest {

  @Mock
  private IRoutingObjHttpClient routingClientMock;

  @Before
  public void createMocks() {
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void testSendRoutingRequest() throws Exception {
    // ...
  }
}

如果您也在使用 PowerMock,那么

@RunWith(MockitoJUnitRunner.class)

可以替换为

@RunWith(PowerMockRunner.class)

这将激活您的 @Mocks 并启用 PowerMock 功能。

尝试检查您调用的方法是否是 final 方法。

Mockito 无法模拟 final 方法。 https://github.com/mockito/mockito/wiki/FAQ

也可能是导入问题,所以请确保您有合适的导入包。

例如,"org.easymock" 包也有一个名为 @Mock 的注解,当然,它不适用于 Mockito 特定设置。

如果您将 junit.jupiter@ExtendWith(MockitoExtension.class) 一起用于测试 class 但 模拟为空 ,请确保 @Test 注释是进口自

import org.junit.jupiter.api.Test;

而不是org.junit.Test;

如果您使用的是 Junit5,则可能会出现同样的问题,因为不再有“@RunWith”注释。

在这种情况下,您应该将 class 注释为:

@ExtendWith(MockitoExtension.class)
public class MyTestClass {
...

您还应该导入您的依赖项(Maven - pom.xml):

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>${mockito.version}</version>
    <scope>test</scope>
</dependency>

对我来说,即使在添加 @RunWith(MockitoJUnitRunner.class) 之后它也不起作用。
事实证明,我犯了一个愚蠢的错误,即从

导入 @Test
import org.junit.jupiter.api.Test;

而不是

import org.junit.Test;

修改后成功了!

对我来说,将注释添加到 class:

@RunWith(MockitoJUnitRunner.class)

修改 Mockito 的版本解决了这个问题。

<dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>2.23.4</version>
        <scope>test</scope>
</dependency>

是什么为我解决了这个问题(结合以上答案和我自己的补充):

  • MockitoAnnotations.initMocks(this);@Before 方法中
  • 测试class必须是public
  • 测试方法必须public
  • import org.junit.Test; 而不是 import org.junit.jupiter.api.Test;

在 Intellij 中执行 command + N --> Test... 时,它会生成(至少作为默认值)一些样板文件,这些样板文件在我的情况下不起作用。

我遇到了同样的问题,但我发现将我的测试(最初是为 JUnit 3 编写并使用遗留 setUp()tearDown() 方法)更新为 JUnit 4 和现代带注释的夹具方法成功了。

此外,如果您使用规则:

@Rule public MockitoRule rule = MockitoJUnit.rule();

确保规则也在 public class 上,否则您将收到消息:

How did getFields return a field we couldn't access?

对我来说,当我添加时它起作用了:

  1. 在 class 级别:
@RunWith(MockitoJUnitRunner.class).
  1. 里面 class:
@Before
      public void createMocks() {
        MockitoAnnotations.initMocks(this);
      }

在测试中添加 @ExtendWith(MockitoExtension.class) 注释 class 它应该可以工作,因为您使用的是 Junit 5+ 版本。 如果您使用的是旧版本的 Junit,请使用 @RunWith(MockitoJUnitRunner.class) 注释。

我遇到了一个问题,我声明了@Mock MyClass myClass,然后试图在我的@BeforeAll 注释方法中模拟一个行为:

@Mock
private MyClass myClass;

...

@BeforeAll
public void init()
{
    ...
    Mockito.when(myClass.something()).thenReturn("Not found")
    ...
}

显然 init() 是在 myClass 的模拟初始化之前执行的,所以 myClass == null inside init()。

解决方案是将注释从@BeforeAll 更改为@BeforeEach。

在对我有用的评论中找到了这个解决方案。对您正在创建的所有模拟执行此操作。

您需要实例化 routingClientMock 例如

routingClientMock = Mockito.mock(RoutingObjHtttpClient.class);