模拟、存根和假对象之间有什么区别[关闭]

2024-05-01

尽管有大量资源,但即使在 SO 上,这些 Q/A 中也仅对其中两个术语进行了比较。

那么,简而言之,它们各自是什么?它们之间有何关系?或者他们根本就没有?


模拟和存根之间的区别非常简单 -模拟可能会让你的测试失败,而存根则不会。仅此而已。此外,您可以将存根视为以下内容提供价值。如今,假货只是两者的通用术语(稍后会详细介绍)。

Example

让我们考虑一种情况,您必须构建一个通过通信协议发送包的服务(具体细节不相关)。您只需提供服务包代码,剩下的事情就由它来完成。给出下面的代码片段,您能否确定哪个依赖项将是存根以及潜在单元测试中的哪个模拟?

public class DistributionService
{
    public double SendPackage(string packageCode)
    {
        var contents = this.packageService.GetPackageContents(packageCode);
        if (contents == null)
        {
            throw new InvalidOperationException(
                "Attempt to send non-exisiting package");
        }

        var package = this.packageBuilder.Build(contents);
        this.packageDistributor.Send(package);
    }
}

很容易看出这一点packageBuilder只是提供价值,并且不可能使任何测试失败。那是一个stub。虽然看起来比较模糊,packageService也是存根。它提供了一个值(从存根的角度来看,我们对该值所做的事情是无关的)。当然,稍后我们将使用该值来测试是否抛出异常,但这仍然在我们的控制范围内(例如,我们准确地告诉存根要做什么,然后忘记它 - 它不应该对测试产生进一步的影响)。

它变得不同packageDistributor。即使它提供了任何价值,它也不会被消耗。然而,呼叫Send似乎是我们实施中非常重要的一部分,我们很可能想要verify它被称为。

至此我们应该得出一个结论packageDistributor is a mock。我们将有一个专门的单元测试来断言Send方法被调用,如果由于某些原因没有被调用 - 我们想知道,因为它是整个过程的重要组成部分。其他依赖项是存根,因为它们所做的只是为其他可能更相关的代码片段提供值。

快速浏览 TDD

存根就是存根,也可以用常量值替换幼稚的实施:

var contents = "Important package";
var package = "<package>Important package</package>";
this.packageDistributor.Send(package);

这本质上就是模拟框架对存根所做的事情——指示它们返回可配置/显式的值。老派,手卷存根通常就是这样做的——返回常量值。

显然,这样的代码没有多大意义,但是任何曾经做过 TDD 的人肯定都见过一堆这样的代码幼稚的实现在班级发展的早期阶段。 TDD 带来的迭代开发通常会有所帮助确定角色你的类的依赖关系。

如今的存根、模拟和赝品

在这篇文章的开头我提到过fake只是一个通用术语。鉴于模拟也可以用作存根(特别是当涉及现代模拟框架时),为了避免混淆,最好将此类对象称为假对象。如今,你可以看到这种趋势正在增长 - 原创模拟存根区别正在慢慢成为过去,并且使用更通用的名称。例如:

  • FakeItEasy 使用fake
  • N替代品用途代替
  • 起订量用途mock(名称是旧的,但无论是存根还是模拟都没有明显的区别)

参考文献,进一步阅读

  • 模拟不是存根 http://martinfowler.com/articles/mocksArentStubs.html作者:Martin Fowler - 您可以看到这篇文章实际上在任何存根/模拟问题下都有链接,这是有原因的
  • 探索测试替身的连续性 http://msdn.microsoft.com/en-us/magazine/cc163358.aspx作者:Mark Seemann - 所有令人困惑的单元测试术语的概述(如果您认为模拟、伪造和存根就足够了,您可能应该知道还有*虚拟**,spy, double以及什么不是)
  • xunitpatterns.com http://www.xunitpatterns.com- 巨大的单元测试模式书籍的支持网站,xUnit 测试模式:重构测试代码 https://rads.stackoverflow.com/amzn/click/com/0131495054作者:杰拉德·梅萨罗斯
  • 单元测试的艺术 https://rads.stackoverflow.com/amzn/click/com/1933988274作者:Roy Osherove - 优秀的单元测试入门书(“模拟可以使测试失败,存根则不会”这是罗伊的话,不是我的)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

模拟、存根和假对象之间有什么区别[关闭] 的相关文章

随机推荐