模拟实例在@Mock 注释后为空

Posted

技术标签:

【中文标题】模拟实例在@Mock 注释后为空【英文标题】:mock instance is null after @Mock annotation 【发布时间】:2015-06-17 21:29:35 【问题描述】:

我尝试运行这个测试:

    @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.

我错过了什么?

【问题讨论】:

你打电话给MockitoAnnotations.initMocks(this)吗? (可能应该在 @Before 方法中)或者,您是否有任何其他 @Rule 您希望初始化您的模拟? (它不是自动的) 您需要实例化 routingClientMock 例如routingClientMock = Mockito.mock(RoutingObjHtttpClient.class); 你也可以在课堂上使用@RunWith(MockitoJUnitRunner.class) 请写作为答案,我会标记它 【参考方案1】:

当你想使用@Mock注解你应该使用MockitoJUnitRunner

@RunWith(MockitoJUnitRunner.class)
public class MockitoTest 

    @Mock
    private IRoutingObjHttpClient routingClientMock;

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


另见this tutorial。

【讨论】:

它对我不起作用总是给出这个错误“dexcache == null(并且找不到默认值;考虑设置'dexmaker.dexcache'系统属性)” @pyus13 这应该是一个有更多代码的新问题。 感谢您的回复,我认为问题在于我在 JUnit Test 中使用它,而一些代码合并了团队中的某个人错误地添加了 dex maker testImplementation 依赖项。从 build.gradle 中删除该行后,事情就开始工作了。谢谢希望这会节省别人的时间。 通过使用@Mock 注释这使得构建失败。 @David 我认为您的问题应该是一个完整示例的新问题。【参考方案2】:

您有三个用于激活@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 
    // ...
  

【讨论】:

在大多数测试类中,@RunWith(MockitoJUnitRunner.class) 可以很好地注入模拟。但在少数测试类中,@RunWith(MockitoJUnitRunner.class) 和 MockitoAnnotations.initMocks(this) 只能一起工作。这个问题有解释吗? 能否请您在 *** 上创建另一个问题并提供完整示例。【参考方案3】:

如果您使用 Junit5,可能会出现同样的问题,因为没有更多的 '@RunWith' 注释。

在这种情况下,您应该使用以下内容注释您的类:

@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>

【讨论】:

对于当今大多数阅读此主题的人来说,这很可能是正确的解决方案。 这个答案确实救了我的命,它可能应该列在所有答案 +1 的最顶端。 2021 年最佳答案 谢谢。你拯救了我的一天。 为我节省了很多时间,谢谢!没错,使用 @RunWith(MockitoJUnitRunner.class) 后,我无法模拟对象,IntelliJ IDE 不断抛出模拟对象为空的错误。最后我所有的测试用例在替换为@ExtendWith(MockitoExtension.class) 后都运行成功了【参考方案4】:

如果您使用junit.jupiter@ExtendWith(MockitoExtension.class) 进行测试类但模拟为空,请确保@Test 注释是从

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

而不是org.junit.Test;

【讨论】:

【参考方案5】:

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

MockitoAnnotations.initMocks(this);@Before 方法中 测试类必须是公开的 测试方法必须公开 import org.junit.Test; 而不是 import org.junit.jupiter.api.Test;

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

【讨论】:

非常感谢你救了我。我的问题是您评论的最后一个问题。太爱了! 我的场景包括@RunWith(PowerMockRunner.class)@PowerMockRunnerDelegate(Parameterized.class)。对于@Parameterized.Parameters 下声明的每个参数,@Before 注释调用一些模拟对象null。没有参数,测试运行良好,没有 NPE。带参数,需要MockitoAnnotations.initMocks(this)。谢谢!【参考方案6】:

对我来说,即使在添加 @RunWith(MockitoJUnitRunner.class) 之后它也不起作用。 原来,我犯了从

导入@Test 的愚蠢错误
import org.junit.jupiter.api.Test;

而不是

import org.junit.Test;

改正后,成功了!

【讨论】:

【参考方案7】:

这也可能是导入问题,因此请确保您有适当的导入包。

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

【讨论】:

【参考方案8】:
    你应该在课堂上使用@RunWith(SpringJUnit4ClassRunner.class) 你必须在@Before方法中调用MockitoAnnotations.initMocks(this);

【讨论】:

为什么是@RunWith(SpringJUnit4ClassRunner.class) 而不是MockitoJUnitRunner.class 你不需要 SpringJUnit4ClassRunner 除非你想将一些 Spring 上下文连接到你的测试中——这本身就是一个非常曲折的段落。【参考方案9】:

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

@Mock
private MyClass myClass;

...

@BeforeAll
public void init()

    ...
    Mockito.when(myClass.something()).thenReturn("Not found")
    ...

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

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

【讨论】:

【参考方案10】:

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

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

【讨论】:

【参考方案11】:

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

    在班级层面:
@RunWith(MockitoJUnitRunner.class).
    课内:
@Before
      public void createMocks() 
        MockitoAnnotations.initMocks(this);
      

【讨论】:

一个就够用@mock注解【参考方案12】:

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

【讨论】:

【参考方案13】:

为我添加注释到类:

@RunWith(MockitoJUnitRunner.class)

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

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

【讨论】:

【参考方案14】:

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

此外,如果您使用的是规则:

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

确保该规则也在公共课程中,否则您将收到消息:

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

【讨论】:

【参考方案15】:

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

你需要实例化 routingClientMock 例如

routingClientMock = Mockito.mock(RoutingObjHtttpClient.class);

【讨论】:

【参考方案16】:

如果你也在使用 PowerMock,那么

@RunWith(MockitoJUnitRunner.class)

可以替换为

@RunWith(PowerMockRunner.class)

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

【讨论】:

以上是关于模拟实例在@Mock 注释后为空的主要内容,如果未能解决你的问题,请参考以下文章

Mockito.mock(SomeClass)和@Mock注释有什么区别?

vue-element-ui 修改mock的模拟数据

什么是@Mock注释感?

Lombok注解

axios + mock.js模拟数据实现前后端分离开发的实例代码

APIAuto:敏捷开发最强大易用的 HTTP 接口工具,机器学习零代码测试生成代码与静态检查生成文档与光标悬浮注释,集 文档测试Mock调试管理 于一体的一站式体验。