【问题标题】:If I am able to call AssertWasCalled method on a Stub, what is the difference between mock and stub?如果我能够在 Stub 上调用 AssertWasCalled 方法,那么 mock 和 stub 有什么区别?
【发布时间】:2011-12-22 21:13:13
【问题描述】:

据我所知,Stub 只是依赖项的替代品。存根不用于验证,它不会通过测试 - 来自《单元测试的艺术》一书。

但似乎从 Rhino Mocks 3.5 开始我可以做到这一点:

var service = MockRepository.GenerateStub<ILuckyService>(); 
service.AssertWasCalled(s=>s.GetLuckyNumberOfTheDay());

如果可以验证是否在 stub 上调用了方法,那么如果我需要使用 stub 或 mock,为什么还要麻烦自己呢?

【问题讨论】:

  • 因为代码干净的原因?
  • 可能它们是相同的:请参阅此问题:stackoverflow.com/questions/477924/… 以及此 Ayende 的帖子:ayende.com/blog/3384/…
  • FakeItEasy 和 NSubstitute 等其他 mocking 框架仅使用单术语 mock/fake/stub。毕竟通常你只是想在你的单元测试中伪造一些东西,你并不关心术语上的差异。

标签: c# .net unit-testing tdd rhino-mocks


【解决方案1】:

使用 Martin Fowler 的文章作为您团队中的共享参考。区别对你的测试的读者来说很重要:当我看到一个存根时,我会忽略它并继续前进。

  • 存根只是为了让您的测试工作(NOP 方法/返回一些固定值)。它不是测试的重点,而是一个附带的细节。 (尽管您的测试场景的强制性细节/依赖关系)
  • 另一方面,模拟是您的主要关注点...您想测试您的操作是否导致满足(模拟)依赖项的特定期望。

这是我的看法。即使 Rhino Mocks 允许您这样做,我也不会在 Stub 上断言。

【讨论】:

  • 我同意你的看法。但是在这种情况下,我们是否能够对 MOCK 对象也能对 STUBS 做任何我们可以做的事情?还是一个比另一个有一些限制?
  • 我刚刚在阅读,似乎没有明显的区别。这是它在文档中所说的 - ayende.com/wiki/… 似乎建议使用存根。另外 Expect()-Do()-Verify() 和 AssertWasCalled 似乎是做同样事情的两种方式。阅读该链接中带下划线的部分,了解何时升级到 Rhino Mock。结论:太复杂了。
  • 100% 同意“太复杂”。当我编写测试时,我最不想做的就是想知道测试是否真的在做我认为的事情。要么坚持 Stub 和 Mock 的既定定义,要么在框架中根本不使用这种区别。
【解决方案2】:

实际上 RhionMocks 中 Mock 和 Stub 类的行为是相同的,可能会让人困惑,even to the creator of RhinoMocks
但是由于stub and mock 之间存在根本区别,因此使用 Rhino Mocks 选择一个而不是另一个,可以让您的代码意图更加清晰。
创建存根时,您只是不希望测试在存根的方法调用上失败(例如,当您使用某些 Log 对象时)。
创建 Mock 时,您需要验证您的代码是否按预期使用了提供的对象(例如,将正确的数据写入数据库)。

【讨论】:

  • 我使用 Stubs + AssertWasCalled() 来验证方法是否已被调用,并认为它是一个更好的方法,Verify()。至少因为它使我的测试保持在 Arrange/Act/Assert 形状。
【解决方案3】:

我总是尝试使用存根。存根和模拟之间的区别(从 RM 的角度来看)是存根在调用期间永远不会抛出异常。如果使用超出预期的其他参数进行调用,则 Mocks(尤其是 Strict 的)将立即抛出。您还可以验证仅对模拟而不是存根的期望。

另一个难题是使用什么:Expect.Call()SetupResult.For()(我倾向于使用后者)。 但我同意所有这些丰富性在大多数情况下都是无用的。这就是为什么我更喜欢 Stubs。

不过,我建议您看一下Nsubstitute——它没有那么乱,而且语法非常富有表现力。只要看看几个例子,你就会立刻爱上它:)

【讨论】:

  • 这并不完全准确:您可以通过调用 AssertWasCalled 来验证存根,如果不期望调用,非严格模拟不会抛出异常,与存根相同。
【解决方案4】:

【讨论】:

  • Martin 的分类不适用于 RhinoMocks 对 Mocks 和 Stubs 的解释。在 RM 中差异不那么明显。
【解决方案5】:

Stub 或 Mock 是概念。您可以创建一个存根并将其用作模拟,反之亦然。我强烈推荐阅读这篇文章 - http://martinfowler.com/articles/mocksArentStubs.html

【讨论】:

    猜你喜欢
    • 2011-11-12
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    • 2011-08-06
    • 2020-10-21
    • 1970-01-01
    相关资源
    最近更新 更多