This code from the documentation让我很困惑:
List list = new LinkedList();
List spy = spy(list);
when(spy.size()).thenReturn(100); // <--- how does this spy know
// not to call the real method????
//using the spy calls *real* methods
spy.add("one");
spy.add("two");
我明白了,Mockito很奇怪,几乎还没有Java。令人感到困惑的是,spy.*
必须在知道它是否包含在when()
或其他内容之前进行全面评估。第一个spy.*
方法究竟是如何调用真实对象的,而后者才调用它?
答案 0 :(得分:2)
根据文档,第一个when(spy.size()).thenReturn(100)
实际上会调用真正的List.size()
方法,请参阅:http://mockito.github.io/mockito/docs/current/org/mockito/Mockito.html#13
然后,每个后续调用都将返回模拟结果。
如果您不希望调用真实方法(例如when(spy.get(0)).thenReturn(...)
可能会抛出IndexOutOfBoundsException
,则必须使用此模式:doReturn(...).when(spy).get(0);
答案 1 :(得分:1)
我不知道确切的实现,但我可以猜一下。
对spy(...)
的调用首先代理给定对象,并将其作为委托调用的引用。
电话
when(spy.size()).thenReturn(100);
实际上相当于
Integer result = spy.size();
OngoingStubbing<Integer> stubbing = when(result); // result is useless
stubbing.thenReturn(100);
在代理上调用size()
的第一个调用。在内部,它可以注册呼叫,例如,在static
(全局)Mockito堆栈上推送它。然后,当您调用when()
时,Mockito从堆栈中弹出,将对size()
的调用识别为需要存根并执行所需的任何逻辑。
这可以解释为什么stubbing in a multithreaded environment是坏事。