简体   繁体   English

获得例外,参数不同:想要:

[英]Getting exception as, Argument(s) are different! Wanted:

@Spy
@InjectMocks
NotificationServiceImpl notificationService;

When i use like above, I am getting exception for a test as, Argument(s) are different: Wanted.当我像上面那样使用时,我得到了一个测试的例外,因为参数不同:想要。 But but while debugging control is going inside all methods and code coverage is happening.但是,当调试控制进入所有方法并且代码覆盖发生时。

@Mock
NotificationServiceImpl notificationService;

When i use like above, I am not getting any exception, but while debugging control is not going inside a few methods its impacting the code coverage.当我像上面那样使用时,我没有得到任何异常,但是虽然调试控制没有进入一些方法,但它会影响代码覆盖率。 Could any one suggest me the proper mocking here.任何人都可以在这里向我推荐合适的 mocking。 So that code coverage will happen as well as no exception will come.这样代码覆盖就会发生,并且不会出现异常。 Stack Trace堆栈跟踪

Argument(s) are different! Wanted:
cwAlarmService.raiseNotificationProcessingAlarm(
    "device_id_value",
    <any string>
);
-> at com.cisco.inventory.service.NotificationMonitorTest.test_run_Exception_CW_Alarm(NotificationMonitorTest.java:189)
Actual invocations have different arguments:
cwAlarmService.raiseNotificationProcessingAlarm(
    "1b8722ad-0b9b-3327-98fb-5016fcf919f5",
    "Exception"
);
-> at com.cisco.inventory.scheduler.NotificationMonitor$TriggerNotificationDataCollection.run(NotificationMonitor.java:100)

    at com.cisco.inventory.service.NotificationMonitorTest.test_run_Exception_CW_Alarm(NotificationMonitorTest.java:189)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

and this is the test这是测试

@Test
    public void test_run_Exception_CW_Alarm() throws IOException, InterruptedException {
        List<DeviceDetails> deviceDetailsList = new ArrayList<>();
        DeviceDetails deviceDetails = new DeviceDetails();
        deviceDetails.setDeviceId(ConstantsTest.DEVICE_ID_VALUE);
        deviceDetails.setCollectionStatus(Constants.COMPLETED);
        deviceDetails.setType("abc");
        deviceDetails.setIP("10.58");
        deviceDetailsList.add(deviceDetails);
        Mockito.when(inventoryDao.getAllDeviceDetails()).thenReturn(deviceDetailsList);
        Mockito.when(inventoryDao.getDeviceDetails(Mockito.any())).thenReturn(deviceDetails);
        NotificationData notificationData = getNotificationData();
        notificationData.setNotificationProcessingStatus(Constants.INIT);
        notificationData.setDeviceId("1b8722ad");
        Mockito.when(inventoryDao.getValidNotificationToBeProcessed(Mockito.any())).thenReturn(notificationData);
        notificationData.setNotificationProcessingStatus(Constants.PROCESSING);
        notificationData.setIsAlarm(Boolean.TRUE);

        List<StringPair> list = populateSVOModelPathStringPairs();
        StaticList.ModelPathMapData modelPathMapData = new StaticList.ModelPathMapData();
        modelPathMapData.setName(Constants.GET_QUERY_MAP_FOR_SVO);
        modelPathMapData.setModelPaths(list);
        StaticList staticList = new StaticList();
        staticList.setModelPathMap(modelPathMapData);
        Optional<StaticList> staticListOptional = Optional.of(staticList);

        Mockito.when(inventoryDao.findStaticListByID(Constants.SVO)).thenReturn(staticListOptional);
        Mockito.when(inventoryDao.saveNotificationProcessingStatus(Mockito.any(),Mockito.any())).thenReturn(notificationData);
        Mockito.doThrow(new RuntimeException("Exception")).when(notificationService).checkAndHandleDeleteNotifications(notificationData);

        notificationMonitor.run();

        Mockito.verify(cwAlarmService, Mockito.timeout(1000)).raiseNotificationProcessingAlarm(eq(ConstantsTest.DEVICE_ID_VALUE), Mockito.anyString());
    }

TL;DR TL;博士

While mocking the methods of a spied object use doReturn(...).when(...) instead of when(...).thenReturn(...)虽然 mocking 间谍 object 的方法使用doReturn(...).when(...)而不是when(...).thenReturn(...)

Longer explanation更长的解释

Although in Mockito the mocks and spies looks similar, there are some important differences.尽管在Mockito中,模拟和间谍看起来很相似,但还是有一些重要的区别。

  • @Mock stubs all the methods. @Mock存根所有方法。 The methods do nothing and return null by default.这些方法什么都不做,默认返回null
  • @Spy does not stub anything unless it is told to. @Spy除非被告知,否则不会存根任何东西。 It invokes the real methods of the spied object by default.它默认调用间谍 object 的真实方法。

There is another important implementation difference:还有另一个重要的实现差异:

  • when(obj.someMethod(...)).thenReturn(value) - invokes the method someMethod and then stubs the method. when(obj.someMethod(...)).thenReturn(value) - 调用方法someMethod然后存根该方法。
  • doReturn(value).when(obj).someMethod(...) - does not invoke the method someMethod and stubs it right away. doReturn(value).when(obj).someMethod(...) - 不调用方法someMethod并立即存根。

These two approaches have similar effect while stubbing mocks.这两种方法在存根模拟时具有相似的效果。 But in case of spies calling the real method of a real object can lead to unwanted side effects.但如果间谍调用真正的 object 的真正方法,可能会导致不必要的副作用。


So when you are using @Spy with when(...).thenReturn(...) there are some hidden side effects, which in your particular case result in generating an actual UUID instead of returning the dummy value "device_id_value" .因此,当您将@Spywhen(...).thenReturn(...)一起使用时,会有一些隐藏的副作用,在您的特定情况下会导致生成实际的UUID而不是返回虚拟值"device_id_value"

This also explains why your unit test works properly while using @Mock .这也解释了为什么您的单元测试在使用@Mock时可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM