模拟实例在@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注释有什么区别?
axios + mock.js模拟数据实现前后端分离开发的实例代码
APIAuto:敏捷开发最强大易用的 HTTP 接口工具,机器学习零代码测试生成代码与静态检查生成文档与光标悬浮注释,集 文档测试Mock调试管理 于一体的一站式体验。