Java Mockito验证一个方法在spy之后被调用一次,尽管它从未被调用

Java Mockito验证一个方法在spy之后被调用一次,尽管它从未被调用,java,junit,mockito,Java,Junit,Mockito,我有一个单元测试,一开始就发现了一个奇怪的问题 GSLClient gslClient = spy(new GSLSolaceClient()); String orgId = "10006"; int orgFlag = Destination.ORG_ID_INPUT_FLAG_APP; String eventId = "11010000"; String scenario = "01"; String inputDCN = "A00";

我有一个单元测试,一开始就发现了一个奇怪的问题

    GSLClient gslClient = spy(new GSLSolaceClient());
    String orgId = "10006";
    int orgFlag = Destination.ORG_ID_INPUT_FLAG_APP;
    String eventId = "11010000";
    String scenario = "01";
    String inputDCN = "A00";
    String GSLRetDCN = "FT0";

    //mock
    when(gslClient.requestTargetDCNFromGSLServer(mockGSLBizSeqNo,orgId, eventId, scenario, orgFlag))
            .thenReturn(buildMockSuccessGSLRespMsg(GSLResponse.ORG_FALG_GSL_INPUT, GSLRetDCN))//success for first time
            .thenThrow(new GSLClient.GSLInvokeTimeoutException("Mock GSL timeout"));//timout for the second time

    verify(gslClient, never()).requestTargetDCNFromGSLServer(mockGSLBizSeqNo,orgId, eventId, scenario, orgFlag);
除了模拟我的对象,我什么也没做,然后我验证mock方法从未被调用

但结果给了我:

org.mockito.exceptions.verification.NeverWantedButInvoked: 
gSLSolaceClient.requestTargetDCNFromGSLServer(
    "MOCKGSLBIZSEQNO_GSL_CACHE_TEST",
    "10006",
    "11010000",
    "01",
    0
);
Never wanted here:
-> at cn.webank.rmb.gsl.GSLCacheTest.test_76789232(GSLCacheTest.java:226)
But invoked here:
-> at cn.webank.rmb.gsl.GSLCacheTest.test_76789232(GSLCacheTest.java:222)


    at cn.webank.rmb.gsl.GSLCacheTest.test_76789232(GSLCacheTest.java:226)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
我想知道是否还有其他地方调用此方法,因此我尝试删除代码

        when(gslClient.requestTargetDCNFromGSLServer(mockGSLBizSeqNo,orgId, eventId, scenario, orgFlag))
            .thenReturn(buildMockSuccessGSLRespMsg(GSLResponse.ORG_FALG_GSL_INPUT, GSLRetDCN))//success for first time
            .thenThrow(new GSLClient.GSLInvokeTimeoutException("Mock GSL timeout"));//timout for the second time
然后结果被传递,证明实际上没有其他地方调用此方法

但是为什么mockito会给我这个结果呢

我试过下面的测试,但它通过了

   {
        //test mock
        Date mockD = spy(new Date());
        when(mockD.getTime())
                .thenReturn(1l)
                .thenThrow(new RuntimeException("mock ex"));
        verify(mockD, never()).getTime();
    }
-------------------方法
requestTargetDCNFromGSLServer
的原始实现如下--------------


你在嘲弄间谍,所以你应该遵循嘲弄的顺序:

    doReturn(buildMockSuccessGSLRespMsg(GSLResponse.ORG_FALG_GSL_INPUT, GSLRetDCN))
    .doThrow(new GSLClient.GSLInvokeTimeoutException("Mock GSL timeout"))
    .when(gslClient).requestTargetDCNFromGSLServer(
             mockGSLBizSeqNo,orgId, eventId, scenario, orgFlag);

在您当前的情况下,您在模拟时调用了一个真正的实现,这就是为什么会出现错误。当您使用开始配置时,预计Mockito可以在
When
方法中“保护”间谍的实际方法调用。

即使您的解决方案可能有所帮助,我也无法重现此问题中的问题。我假设还有另一个问题。我尝试了另一个模拟对象
Date
,并模拟了它的
getTime()
方法,但没有问题。所以,对于我的紧急需要,我如何解决我的问题时,嘲笑,你也能指出为什么,因为我是新的莫基托。然后应该讨论问题的原因,我的意思是为什么我对
Date
Ok使用相同的方法时没有问题,但我会坚持测试您的代码,因为它可能包含一些微妙的细节。在我的更改后,您是否会收到相同的错误?@MaciejKowalski,是的,我将我的模拟方法删除到您的测试代码中,它可以工作,但我必须模拟第二个返回结果,因此它不是等效的,请更新您的答案。并指出两者的区别。非常感谢。“好了,”解决方案补充道。您只是从前面而不是从后面堆叠。您能否提供
requestTargetDCNFromGSLServer
方法的声明?在界面和类中都有。@SergheyBishyr,已在问题中显示。并且没有接口,此方法在抽象类中声明
GSLClient
    doReturn(buildMockSuccessGSLRespMsg(GSLResponse.ORG_FALG_GSL_INPUT, GSLRetDCN))
    .doThrow(new GSLClient.GSLInvokeTimeoutException("Mock GSL timeout"))
    .when(gslClient).requestTargetDCNFromGSLServer(
             mockGSLBizSeqNo,orgId, eventId, scenario, orgFlag);