Mockito间谍在间谍活动时如何知道?

时间:2014-11-13 23:10:53

标签: java unit-testing mocking mockito spy

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.*方法究竟是如何调用真实对象的,而后者才调用它?

2 个答案:

答案 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是坏事。