[英]Mockito throws NPE when stubbing method from base class
I use a Hystrix (v. 1.5.6) command in my tested class, and I'm trying to mock it with Mockito (v. 1.10.19). 我在经过测试的课程中使用了Hystrix(v.5.6.1)命令,并且尝试使用Mockito(v.1.10.19)模拟它。
Recently I've had to add a special behavior if the command failed because of a timeout: 最近,如果命令由于超时而失败,我不得不添加特殊行为:
try {
result = command.execute();
} catch (HystrixRuntimeException err) {
if (command.isResponseTimedOut()) {
/** do stuff **/
}
/** do stuff **/;
}
This is the code in my test class : 这是我的测试课中的代码:
HttpClientCommand command = mock(HttpClientCommand.class);
when(commandFactory.get(anyString(), anyString(), anyString(), anyMapOf(String.class, String.class))).thenReturn(command);
when(command.execute()).thenThrow(hystrixRuntimeException);
when(command.isResponseTimedOut()).thenReturn(false);
My HttpClientCommand
extends the HystrixCommand
class. 我的
HttpClientCommand
扩展了HystrixCommand
类。 The execute
method is in this class, and I have no problem stubbing it. execute
方法在此类中,我对它进行存根没有问题。
The HystrixCommand
class then extends the AbstractCommand
class, where the isResponseTimedOut
method is. 所述
HystrixCommand
类然后扩展AbstractCommand
类,其中isResponseTimedOut
方法。 When I try to stub it, I get a NPE from Mockito (on the when(command.isResponseTimedOut()).thenReturn(false);
line, before calling any method on my tested class). 当我尝试对它进行存根时,我从Mockito获得了NPE(在对测试类调用任何方法之前,在
when(command.isResponseTimedOut()).thenReturn(false);
行上)。
Stack trace : 堆栈跟踪 :
java.lang.Exception: Unexpected exception, expected<my.custom.exception> but was<java.lang.NullPointerException>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.NullPointerException
at com.netflix.hystrix.AbstractCommand.isResponseTimedOut(AbstractCommand.java:1809)
at com.netflix.hystrix.HystrixCommand.isResponseTimedOut(HystrixCommand.java:46)
at com.myClassTest.testGetLocation_shouldThrowCustomException_whenRequestException(myClassTest.java:300)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:19)
... 22 more
How can I stub this method? 如何存根此方法?
OK the issue is due to a bug with CGLIB, mockito 1.x uses CGLIB. 好的,问题是由于CGLIB的错误所致,mockito 1.x使用CGLIB。 When the method to mock is declared in a non public parent, then CGLIB doesn't intercept the method, hence it executes the real code.
当在非公共父级中声明要模拟的方法时,CGLIB不会拦截该方法,因此它将执行实际代码。 The issue is still available on our old issue tracker : issue 212
该问题在我们的旧问题跟踪器上仍然可用: 问题212
Two options : 两种选择:
Write a public overload in HttpHystrixCommand
that will invoke the super method, but since the abstract command have a lot of methods to handle failure, this is probalby not an option that will scale very well. 在
HttpHystrixCommand
中编写一个公共重载,该重载将调用super方法,但是由于abstract命令具有许多处理失败的方法,因此probalby并不是一个很好扩展的选项。
Use mockito 2. We have worked with the developer of ByteBuddy – Rafel Winterhalter – to replace CGLIB. 使用嘲笑2。我们已经与ByteBuddy的开发人员Rafel Winterhalter一起替换了CGLIB。 ByteBuddy does not have the same shortcomings of CGLIB which was almost abandonned for years.
ByteBuddy没有CGLIB的缺点,而CGLIB的缺点已被放弃了好多年。 Current version is 2.2.29 and at the time of this anwer regular updates are released.
当前版本是2.2.29,并且在此之时会定期发布更新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.