Rhino Mocks 上的模拟和存根之间有什么区别?

我还没有充分使用这个并且通常使用模拟,但是我想知道这两者之间的区别是什么,以及何时在 Rhino Mocks 上使用一个或另一个。

更新:

我还在 Ayende 的原话中找到了问题的答案:

存根和模拟之间的区别

您可以在本文中获得这些术语的实际定义: 嘲笑不是存根。我想从犀牛模仿者的角度来关注这个差异。

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

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

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

65005 次浏览

根据 这个

... 简单地说,Mock 和 Stub 对象之间是有区别的 RhinoMocks 认识到允许我们编写更好的测试 说明他们的目的。

模拟对象用于定义期望,例如: 在这个场景中,I 期望方法 A ()被这样那样的参数调用 记录并核实这些期望。

另一方面,存根有一个不同的用途: 它们不会被记录下来 或者验证期望,而是允许我们“替换”行为, 状态的“假”对象,以利用一个测试场景..。

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

对于 Moq 框架,setup 方法是 STUB,而 Verify 方法是 Mock

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

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

存根

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

嘲笑

Mock 是带有实现的存根。如果测试下的函数与模拟对象交互,我们可以验证模拟是否如我们预期的那样进行了交互。

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

总而言之

Mock 是带有实现的存根,它允许我们测试副作用。

这个区别还重要吗?

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

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

你应该用哪个?

您可能会发现,您开始创建存根,然后您可能会发现,您需要为一些对象创建完整的模拟。您可能希望一边走一边嘲笑所有内容,或者您可能只想在需要的地方嘲笑。