ChatGPT解决这个技术问题 Extra ChatGPT

Rhino Mocks 上的 mock 和 stub 有什么区别?

我玩得还不够多,通常使用模拟,但我想知道这两者之间有什么区别以及何时在 Rhino Mocks 上使用其中一个。

更新:

我还在 Ayende's words 中找到了我的问题的答案:

存根和模拟之间的区别

您可以在本文中获得这些术语的实际定义:Mocks Aren't Stubs。我想从 Rhino Mocks 的角度关注不同之处。

模拟是我们可以设置期望的对象,它将验证预期的动作确实发生了。存根是您用来传递给被测代码的对象。您可以对其设置期望,因此它会以某些方式起作用,但这些期望永远不会得到验证。存根的属性会自动表现得像普通属性一样,您不能对它们设置期望。

如果您想验证被测代码的行为,您将使用具有适当期望的模拟,并进行验证。如果您只想传递一个可能需要以某种方式执行的值,但不是此测试的重点,您将使用存根。

重要提示:存根永远不会导致测试失败。


C
CharlesB

根据this

... 简而言之,Mock 和 Stub 对象之间存在差异,RhinoMocks 认识到允许我们编写更好地说明其目的的测试。模拟对象用于定义期望,即:在这种情况下,我希望使用这样和这样的参数调用方法 A()。模拟记录并验证这种期望。另一方面,存根有不同的目的:它们不记录或验证期望,而是允许我们“替换”“假”对象的行为、状态以利用测试场景......


我发现了另一个有用的帖子,它与这个问题的接受答案相同的信息 - martinfowler.com/articles/mocksArentStubs.html
s
superluminary

一般来说,单元测试调用函数和方法,然后检查是否发生了预期的行为。这些函数和方法可能需要参数。我们使用存根和模拟来满足这些参数。我们有时也可以模拟全局对象。

存根

Stub 是一个很小的假对象,您的测试可以将其用作参数以使函数调用正常工作。这让我们可以验证被测函数的行为。它不允许我们验证任何副作用,因为存根没有实现。

模拟

Mock 是一个带有实现的存根。如果我们的被测函数与我们的模拟对象交互,我们可以验证模拟是否已按预期进行交互。

例如,假设我们有一个模拟 User 对象,并且我们想要验证 session.login 方法是否有效,我们可能想要检查 user.lastLoggedIn 是否已设置。我们可以创建一个实现此方法的模拟用户。当我们调用 session.login 时,我们可以断言 user.lastLoggedIn 具有我们预期的状态。

总结一下

模拟是带有实现的存根,它可以让我们测试副作用。

这种差异仍然重要吗?

就像明喻和隐喻之间的区别一样,存根和模拟之间的区别是微妙的和历史的,并且可能更多地与测试世界中不同的社区和哲学有关,而不是任何主要的技术差异。

它们代表了稍微不同的测试方法。模拟可以像存根一样编写。存根通常可以扩展为模拟。

你应该使用哪个?

您可能会发现您开始创建存根,然后您可能会发现您需要为某些对象创建完整的模拟。您可能想随时模拟所有内容,或者您可能只想在需要的地方模拟。


H
Hassan Boutougha

Mock 和 stub 之间的区别:使用 stub,您可以修复单元测试的输入:因此您的单元测试不会对 stub 进行断言,而 Stub 通过重写某些方法的实现来修复假对象的行为。使用 Mock,您可以修复单元测试的输出:因此您的单元测试通过检查模拟对象中的内部交互来对您的模拟对象产生期望。


您似乎在说您的测试应该“检查”模拟的输出。如果这就是你所说的,那你就错了。不应该测试模拟;它在那里,因此您可以测试其他代码。还是你的最后一句话有别的意思?
嗨,安德鲁,正如我用 Mock 写的那样,你修复了测试的输出,所以你不会测试它。否则我已经写了 Mock 允许你检查交互(预期行为......;-)
好吧,这更有意义。感谢您的澄清!
>不在存根上作出断言 为什么在许多 assertion libraries 中仍然存在方法又名 should have been called with 来断言 stub 参数。
c
codebased

在 Moq 框架的情况下 - 设置方法是存根,而验证方法是模拟


S
Sean

我还注意到的一件事是,当我使用 MockRepository.GenerateMock 时,我需要明确设置对特定方法调用的期望以拦截该调用。使用存根,它似乎会自动拦截任何方法,只要它是虚拟的。