【问题标题】:How does a Mockito spy know when it is spying?Mockito 间谍如何知道它何时进行间谍活动?
【发布时间】:2014-11-13 23:10:53
【问题描述】:

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.* 方法到底怎么会不调用真实对象,而后面的方法会调用呢?

【问题讨论】:

标签: java unit-testing mocking mockito spy


【解决方案1】:

根据文档,第一个 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);

【讨论】:

  • 这是真的。我提倡始终使用doReturn(...).when(...),而不是担心何时需要doReturn(...).when(...),何时可以使用when(...).thenReturn(...)。事实上,我已经在这个网站上发布了 Mockito 答案,我建议不要使用 when(...).thenReturn(...)
  • @DavidWallace 你的意思是你建议在使用间谍时总是使用 doReturn() ,或者总是使用它,即使是模拟?我倾向于总是将它与间谍一起使用,但发现经典的 wen(...).then... 更具可读性,因此将其用于模拟。
  • 我更喜欢使用它,即使是模拟。当一个语法涵盖所有​​情况时,学习两种语法是没有意义的。当when/thenReturn 不起作用时,很难记住所有情况。 @JBNizet
  • @JBNizet - 看看我在 stackoverflow.com/q/11462697 上的回答。看来我错误地声明 when 不能用于间谍。在我写这篇文章的时候,这可能是真的;我不知道。所以我会回去纠正这个答案。无论如何,我回答的基本信息仍然是正确的。
【解决方案2】:

我不知道具体的实现,但我可以猜测一下。

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 生意不好。

【讨论】:

  • @DavidWallace 你会让我看看源代码,不是吗?
  • 嗯,我正在考虑自己去看看源代码,只是为了提醒自己。但你实际上非常接近。没有全局堆栈,并且存根调用在 spy 本身中注册。但所有其他细节都是正确的。我想我对你投了反对票太仓促了,我现在就删除我的反对票。
  • 嗯,不得不做一个微不足道的编辑来删除我的反对票。我有时讨厌这个网站。
  • ... 而spy 创建的东西不使用委托。它在一个为存根和验证添加逻辑的类中,但对于它的所有方法,它都调用自身的父方法,而不是某个委托对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
相关资源
最近更新 更多