【问题标题】:When to use mocking versus faking in C# unit testing?何时在 C# 单元测试中使用模拟与伪造?
【发布时间】:2010-11-28 00:42:24
【问题描述】:

任何人都可以提出指导方针,建议选择模拟与伪造的理想场景,即手动设置基本要素吗?

我对如何处理这种情况有点困惑。

【问题讨论】:

    标签: c# .net unit-testing tdd


    【解决方案1】:

    嗯,你有一些事情需要解决。您需要了解两个基本知识:命名法和最佳实践。

    首先,我想为您提供一个来自伟大测试人员 Roy Osherove 的精彩视频资源:

    Roy Osherove 的单元测试评论

    他开始说他有 对测试工具进行了一些审查 附带几个开源 项目。你可以在这里找到那些: http://weblogs.asp.net/rosherove/archive/tags/TestReview/default.aspx

    这些基本上是视频评论 他会带你完成这些测试 驾驭并告诉你什么是好的 什么是坏的。很有帮助。

    罗伊也有一本我看懂的书 非常好。

    命名法

    此播客将提供帮助 非常http://www.hanselminutes.com/default.aspx?showID=187

    不过,我会解释一下播客 (Hanselminutes 的介绍音乐是 可怕):

    基本上你用一个 隔离框架(如 Moq、Rhino Mocks、Type Mock 等)称为 假的

    fake 是在使用期间使用的对象 测试您正在测试的代码 可以调用代替生产代码。 一个假的用来隔离你的代码 正在尝试从其他部分进行测试 你的申请。

    有(主要)两种类型的赝品存根模拟

    mock 是您放入的假货 放置以便您正在测试的代码 可以呼唤它,你断言 呼叫是用正确的 参数。下面的示例只是 这使用最小起订量隔离 框架:

    [TestMethod]
    public void CalculateTax_ValidTaxRate_DALCallIsCorrect()
    {
        //Arrange
        Mock<ITaxRateDataAccess> taxDALMock = new Mock<ITaxRateDataAccess>();
        taxDALMock.Setup(taxDAL => taxDAL.GetTaxRateForZipCode("75001"))
                      .Returns(0.08).Verifiable();
    
        TaxCalculator calc = new TaxCalculator(taxDALMock.Object);
    
        //Act
        decimal result = calc.CalculateTax("75001", 100.00);
    
        //Assert
        taxDALMock.VerifyAll();
    }
    

    存根几乎与 模拟,除了你把它放在适当的位置 确保您正在测试的代码 从其取回一致的数据 调用(例如,如果您的代码调用 数据访问层,存根将 返回假数据),但你没有 断言存根本身。那 是,您不需要验证 方法称为您的虚假数据访问 层——你正在尝试测试 别的东西。您提供存根 得到你想要的方法 测试以隔离工作。

    这是一个带有存根的示例:

    [TestMethod]
    public void CalculateTax_ValidTaxRate_TaxValueIsCorrect()
    {    
        //Arrange
        Mock<ITaxRateDataAccess> taxDALStub = new Mock<ITaxRateDataAccess>();
        taxDALStub.Setup(taxDAL => taxDAL.GetTaxRateForZipCode("75001"))
                      .Returns(0.08);
    
        TaxCalculator calc = new TaxCalculator(taxDALStub.Object); 
    
        //Act
        decimal result = calc.CalculateTax("75001", 100.00);
    
        //Assert
        Assert.AreEqual(result, 8.00);
    }
    

    请注意,我们正在测试 方法的输出,而不是 该方法调用了 另一个资源。

    起订量并不是真正的 API 模拟和存根之间的区别 (注意两者都被宣布为 Mock&lt;T&gt;),但是这里的用法是 在确定类型时很重要。

    希望这能帮助你直截了当。

    【讨论】:

    • Ayende(Rhino Mocks 的创建者)最近宣布,他将放弃 Mock vs Stub,并在下一个版本的 Rhino Mocks 中将所有内容都变成 Fake。有些人会争辩说,如果知道某物是 Stub 而不是 Mock,您会获得更多知识,但这有点挑剔。如果你不在乎,就一直使用 Mocks,不要断言他们的假设。它可以让您省去必须弄清楚使用哪个的麻烦。
    • 很好的解释安德森。我不熟悉 fakes 或 faking,但熟悉 Mocking 和 Stubs。假命名法从何而来?
    • @Anderson Imes 对不起,我没有更明确。我理解你的描述,这已经足够了。我的意思是谁想出了“假货”的命名法。我以前从未在这种情况下看到过它,而且我读过的所有内容一直都是 Mocks vs Stubs。我也订阅了 Ayende 的博客,但从未见过他在同一句话中提到 Mocks/Stubs 和 Fakes。
    • +1 我不知道我是怎么错过这个问题的,但这是一个很好的解释。
    • 为什么人们对这样的答案投反对票而不提供理由?
    【解决方案2】:

    至少有 5 种不同类型的测试替身:假人、存根、模拟、间谍和假货。一个很好的概述是http://code.google.com/testing/TotT-2008-06-12.pdf,它们也被归类在http://xunitpatterns.com/Mocks,%20Fakes,%20Stubs%20and%20Dummies.html

    【讨论】:

      【解决方案3】:

      你想测试一段代码,对,比方说一个方法。您的方法从 http url 下载文件,然后将文件保存在磁盘上,然后邮寄文件在磁盘上。所有这三个动作当然都是您的方法调用的服务类,因为它们很容易模拟。如果您不模拟这些,您的测试将在每次运行该测试时下载内容、访问磁盘并发送消息。然后,您不仅要测试方法中的代码,还要测试下载、写入磁盘和发送邮件的代码。现在如果你在模拟这些,你只是在测试方法代码。例如,您还可以模拟下载失败,以查看您的方法的代码是否正确运行。

      现在,至于伪造,我通常伪造只保存值并且没有太多逻辑的类。如果您要发送一个包含一些值的对象,这些值在方法中会发生变化,您可以在测试中读取它以查看该方法是否正确。

      当然,规则可以(有时必须)稍微改变一下,但一般的思维方式是测试您的代码,并且只测试您的代码。

      【讨论】:

        【解决方案4】:

        The Little Mocker,来自 Bob Martin,是关于该主题的非常好的读物。

        [...] 很久以前,一些非常聪明的人写了一篇论文,介绍并定义了 Mock Object 一词。许多其他人阅读并开始使用该术语。其他没有读过论文的人听到了这个词,并开始用更广泛的含义来使用它。他们甚至把这个词变成了动词。他们会说,“让我们模拟出那个对象吧。”或者“我们有很多模拟工作要做。”

        文章解释了 mocks、fakes、spys 和 stubs 之间的区别。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-07
          • 1970-01-01
          • 1970-01-01
          • 2012-07-02
          • 2011-04-11
          • 1970-01-01
          相关资源
          最近更新 更多