2016-12-08 46 views
0

我在我的測試類中使用Hystrix(1.5.6)命令,我試圖用Mockito(v。1.10.19)來嘲笑它。Mockito在從基類中剔除方法時拋出NPE

最近,我不得不添加一種特殊的行爲,如果命令失敗,因爲超時:

try { 
    result = command.execute(); 
} catch (HystrixRuntimeException err) { 
    if (command.isResponseTimedOut()) { 
     /** do stuff **/ 
    } 
    /** do stuff **/; 
} 

這是在我的測試類代碼:

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

HttpClientCommand延伸HystrixCommand類。 execute方法在這個類中,我沒有問題存根。

HystrixCommand類然後擴展AbstractCommand類,其中isResponseTimedOut方法是。當我嘗試將它存根時,我從Mockito獲得一個NPE(在when(command.isResponseTimedOut()).thenReturn(false);行上,在對我的測試類調用任何方法之前)。

堆棧跟蹤:

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 

我如何存根這個方法?

+0

你有堆棧跟蹤嗎?哪些版本mockito,hystrix,jdk,...? – Brice

+0

我編輯了我的帖子 – Adrien

回答

1

好的問題是由於CGLIB的錯誤,mockito 1.x使用CGLIB。當模擬方法在非公共父級中聲明時,CGLIB不會攔截該方法,因此它會執行真正的代碼。這個問題仍然可以在我們的老問題跟蹤:issue 212

兩個選項:

  1. HttpHystrixCommand公共重載將調用父類方法,但由於抽象的指令有很多的方法處理失敗,這是probalby不是一個可以很好擴展的選項。

  2. 使用mockito 2.我們與ByteBuddy - Rafel Winterhalter的開發人員合作,以取代CGLIB。 ByteBuddy沒有像CGLIB那樣幾乎被放棄多年的缺點。當前版本是2.2.29,並在此時發佈定期更新。

相關問題