文档中的这段代码完全让我感到困惑:
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很奇怪,几乎还在爪哇。令人困惑的是spy.*
必须全面评估,然后才能知道它是否包裹在when()
或其他东西中。第一种spy.*
方法究竟如何不调用真正的对象,而后一种方法
根据文档,第一个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);
我不知道确切的实现,但我可以猜测。
对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()
调用识别为需要存根,并执行执行此操作所需的任何逻辑。
这可以解释为什么在多线程环境中存根是一件坏事。