【问题标题】:Why should I favour stubs over mocks?为什么我应该更喜欢存根而不是模拟?
【发布时间】:2017-01-01 01:29:25
【问题描述】:

我经常读到应该避免模拟并喜欢存根。

FakeItEasy 和 NSubstitute 之类的隔离框架在大多数情况下使模拟或存根依赖项变得非常容易。这些框架本身并不区分存根或模拟,而是将它们统称为假货或替代品。据我所知,在“模拟”的早期,创建模拟对象非常困难,因为使用了繁琐的记录和重放机制。不过今天好像没什么大区别了。

那么为什么我应该更喜欢存根而不是模拟呢?为什么模拟比存根更脆弱?

【问题讨论】:

    标签: c# unit-testing mocking stubbing


    【解决方案1】:

    你不应该“更喜欢”存根而不是 Mocks;相反,您应该为工作选择正确的工具

    Mocks for Commands, Stubs for Queries

    【讨论】:

    • 感谢您的回答。也许我应该问另一个问题。为什么 Mocks 比 stub 造成的伤害更大,或者为什么 mock 比 stub 更脆?
    • 我希望有 100K+ 代表的人能给出更好的答案。例如,您可以用自己的话定义“存根”和“模拟”的概念(如您所知,不建议仅链接答案)。然而,这个答案的最大问题是它基于“旧”(2007)书中有缺陷的“模拟”定义,这与实际模拟库提供的内容相矛盾。即,理论与实践之间存在脱节。
    • @Rookian 我认为这个问题的前提有点缺陷。正如 Gerard Meszaros 在他那本旧的(显然没用的)书中解释的那样,命令产生 间接输出 而不是查询产生的 直接输出。你经常可以把间接输出变成直接输出,反之亦然,所以它们实际上是等价的。如果我不得不推测,人们不喜欢 Mocks,因为他们倾向于让 Mocks 彼此交互过多,但这更多是与一次做“太多”有关的问题,而不是 Mocks 本身的问题......
    • @MarkSeemann 将间接输出转换为直接输出让我想起了在发布事件时使用消息传递而不是“调用 void 方法”的想法。然后,您可以验证该事件是在队列中还是仅在事件列表中。请参阅 codebetter.com/gregyoung/2008/02/13/mocks-are-a-code-smell 任何关于这个想法的 cmets :) ?
    • @Rookian 恐怕没有时间(重新)阅读这篇文章,但这听起来相当。当然,这些天来,我更喜欢函数式编程,这意味着我倾向于另一种方式,将间接输出转换为表示“消息”或事件的直接输出。
    【解决方案2】:

    至少对于最近的模拟工具来说,用存根和模拟来打扰是没有意义的。在实践中,由模拟库创建的模拟和存根是一回事。这就是它应该的样子。

    使用可用于 Java 的模拟库(如果我没记错的话,也可用于 C#.NET),您不能“仅”创建一个存根。你总是得到一个可以验证期望的模拟对象。

    【讨论】:

    • “你总是得到一个可以验证期望的模拟对象”是吧?您不会对存根进行任何验证。两者还是有区别的。
    • @Rookian 你能指出任何允许你创建一个存根的模拟库,在这个库上无法验证期望吗?我不知道有任何这样的图书馆。
    • 这样的库不会创建存根或模拟,而是一个假对象,可以用作存根或/和模拟。
    • @Rookian 哪些库?所有的 Java 模拟库都会创建模拟,而不是伪造或存根(我应该知道,因为我创建了其中一个)。也许在 .NET 世界中情况有所不同,但我想这更像是一个术语而非实际差异。
    • @Rookian 谢谢。我查看了FakeItEasy,但它只是出于营销原因选择了术语,将所有内容称为“假货”。请注意,此选择与知名作者给出的定义不一致:请参阅Martin Fowler's definitionMeszaros' definitionNSubstitute 简单地称一切为“替代品”。所以,事实上,他们通过将模拟和存根视为基本相同,从而证实了我所说的。
    猜你喜欢
    • 2011-04-01
    • 2013-04-30
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2011-05-10
    • 2013-12-01
    • 2017-12-21
    • 2011-02-16
    相关资源
    最近更新 更多