【问题标题】:Understanding stubs, fakes and mocks.了解存根、伪造品和模拟物。
【发布时间】:2013-02-15 09:48:35
【问题描述】:

我刚开始看Professional Test Driven Development with C#: Developing Real World Applications with TDD

我很难理解 stub、fakes 和 mocks。据我目前了解,它们是用于对项目进行单元测试的假对象,并且模拟是一个带有条件逻辑的存根。

我认为我已经了解到的另一件事是,模拟与依赖注入有某种关系,这是我昨天才理解的概念。

我不明白为什么我会实际使用它们。我似乎在网上找不到任何能正确解释它们的具体例子。

谁能给我解释一下这个概念?

【问题讨论】:

标签: unit-testing mocking tdd stubs


【解决方案1】:

正如我过去所读到的,这就是我认为每个术语所代表的含义

存根

在这里,您将方法的结果存根为已知值,只是为了让代码运行没有问题。例如,假设您有以下内容:

public int CalculateDiskSize(string networkShareName)
{
    // This method does things on a network drive.
}

你不关心这个方法的返回值是什么,它不相关。另外,如果网络驱动器不可用,则执行时可能会导致异常。因此,您将结果存根以避免该方法的潜在执行问题。

所以你最终会做这样的事情:

sut.WhenCalled(() => sut.CalculateDiskSize()).Returns(10);

假的

使用 fake 是在返回虚假数据,或创建对象的虚假实例。一个经典的例子是存储库类。采取这种方法:

public int CalculateTotalSalary(IList<Employee> employees) { }

通常,上述方法将传递从数据库中读取的员工集合。但是,在您的单元测试中,您不想访问数据库。所以你创建了一个虚假的员工列表:

IList<Employee> fakeEmployees = new List<Employee>();

然后您可以将项目添加到 fakeEmployees 并断言预期结果,在本例中为总工资。

模拟

使用模拟对象时,您打算验证这些模拟对象的某些行为或数据。示例:

您想验证在测试运行期间是否执行了特定方法,这是一个使用 Moq 模拟框架的通用示例:

public void Test()
{
    // Arrange.
    var mock = new Mock<ISomething>();

    mock.Expect(m => m.MethodToCheckIfCalled()).Verifiable();

    var sut = new ThingToTest();

    // Act.
    sut.DoSomething(mock.Object);

    // Assert
    mock.Verify(m => m.MethodToCheckIfCalled());
}

希望以上内容有助于澄清一些事情。

编辑: Roy Osherove 是测试驱动开发的知名倡导者,他有一些关于该主题的非常好的信息。您可能会发现它非常有用:

http://artofunittesting.com/

【讨论】:

  • 信息量很大。我一直认为假货和模拟物是可以互换的。我每天都在这里学习新东西:) +1
  • Mocks 中的“m”是什么? ISomething 是我们正在测试的类吗?
  • m 是传递给Expect() 函数的参数。它是一个 lambda 表达式。它没有在任何地方声明,它只是存在于Expect() lambda 中。 var mock = new Mock&lt;ISomething&gt;(); 表示您正在创建一个实现ISomething 的对象,所以ISomething 是一个接口,而不是一个对象。然后,您可以使用mock 来控制方法在调用时的响应方式,例如通过Expect() 函数。
【解决方案2】:

它们都是测试替身的变体。这是一个很好的参考资料,解释了它们之间的区别:http://xunitpatterns.com/Test%20Double.html

另外,来自 Martin Fowler 的帖子:http://martinfowler.com/articles/mocksArentStubs.html

Meszaros 使用术语 Test Double 作为任何类型的通用术语 用于测试目的的假装物体代替真实物体。 这个名字来源于电影中特技替身的概念。 (之一 他的目的是避免使用任何已经被广泛使用的名称。) Meszaros 然后定义了四种特殊的双精度:

  1. 虚拟对象:被传递但从未实际使用过。通常他们 仅用于填充参数列表。
  2. 假对象实际上有工作实现,但通常采取一些捷径,这使得 它们不适合生产(内存数据库是一个很好的 示例)。
  3. 存根为测试期间拨打的电话提供预设答案, 通常对编程之外的任何东西都没有反应 为测试。存根还可以记录有关呼叫的信息,例如 一个电子邮件网关存根,它记住它“发送”的消息,或者可能 只有它“发送”了多少条消息。
  4. Mocks 就是我们在这里讨论的内容:预先编程了期望的对象,这些对象形成了一个 他们预计将收到的呼叫的规范。

在这些类型的替身中,只有模拟坚持行为验证。这 其他双打可以并且通常会使用状态验证。模拟 实际上,在锻炼阶段确实表现得像其他双打一样,因为 他们需要让 SUT 相信它正在与它的真实对话 合作者。

【讨论】:

    【解决方案3】:

    这本 PHP 单元的手册作为介绍帮助了我很多:

    “有时很难测试被测系统(SUT),因为它依赖于无法在测试环境中使用的其他组件。这可能是因为它们不可用,它们不会返回结果"更多:https://phpunit.de/manual/current/en/test-doubles.html

    在寻找“test doubles”时,我发现更好的“介绍”,因为 mocks、fakes、stubs 和其他都是已知的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 2011-07-07
      • 2015-03-06
      • 2010-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多