doAnswer in mockito - when is it lazy evaluation and when is it eager?

独自空忆成欢 提交于 2019-12-11 10:49:41

问题


I'm using mockito spy with this code:

Mockito.doAnswer(new Answer() {
    Object answer(InvocationOnMock invocation) {
         ImagesSorter mock = (ImagesSorter) invocation.getMock();
         Object[] args = invocation.getArguments();

         return mock.sortImages((List<Image>) args[0], (UserInfo) args[1],
                 fakeNowDate);
    }
}).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);

And I see the answer() is called eagerly when the struct is:

when(spy.method())./*...*/.

but it's lazy evaluation when the struct is:

/*...*/.when(spy).method()

Shouldn't it be vise versa? Meaning /*...*/.when(spy).method() is eager versus when(spy.method())./*...*/. is lazy? Like do..while loop ?

I couldn't find documentation for that


回答1:


One thing you should notice about this syntax:

when(spy.method()).thenAnswer(someAnswer);

Is that the first thing Java will do when evaluating it is to run:

     spy.method()

...so that it can pass an accurate return value into the when method. Of course, when discards its parameter and just reads the last call to a mock, but Java can't know that from the syntax. For the very first call to when on a mock, the method should have no exceptions or side effects, but that assumption doesn't hold on spies or on methods that you've already stubbed.


In general, doAnswer and other doVerb methods have two key uses: stubbing void methods and overriding already-defined behavior (i.e. for spies and already-stubbed methods).

Void methods

// Doesn't work: voidMethod has no return value, so when() has no parameter
when(yourMock.voidMethod()).thenThrow(new RuntimeException());
// This works, because it skips reading the voidMethod return value:
doThrow(new RuntimeException()).when(yourMock).voidMethod();

Already-stubbed methods

// Doesn't work: This contains a call to dangerousMethod!
when(yourSpy.dangerousMethod()).thenReturn(safeValue);
// This works, because the call to dangerousMethod happens on a dummy copy of yourSpy:
doReturn(safeValue).when(yourSpy).dangerousMethod();

As noted in lkrnac's answer, Mockito describes this latter case in the "important gotcha on spying real objects!" in top-level Mockito documentation.




回答2:


I believe that the /*...*/.when(spy).method() syntax for spies is Mockito implementation detail. If you think about that, how would you implement Mockito functionality to stub method on spy in this call when(spy.method())./*...*/, when you don't want to call real method? You need to have different API for spies because API used for mocks is not suitable.

Here is relevant documentation (see section "Important gotcha on spying real objects!"): https://mockito.googlecode.com/svn/tags/latest/javadoc/org/mockito/Mockito.html#13



来源:https://stackoverflow.com/questions/26157851/doanswer-in-mockito-when-is-it-lazy-evaluation-and-when-is-it-eager

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!