2013-02-15 60 views
9

我刚刚开始阅读Professional Test Driven Development with C#: Developing Real World Applications with TDD了解存根,假货和嘲笑。

我很难理解存根,假货和嘲笑。从我目前了解的情况来看,它们是用于单元测试项目目的的假对象,并且模拟是一个存在条件逻辑的存根。

另一件我认为我已经选择的事情是,嘲笑与依赖注入有关,这是我昨天才理解的一个概念。

我没有得到的是为什么我会真正使用它们。我似乎无法在网上找到任何具体的例子来正确解释它们。

任何人都可以向我解释这个概念吗?

+2

阅读本http://xunitpatterns.com/Mocks,%20Fakes,%20Stubs%20and%20Dummies.html这http://martinfowler.com/articles/mocksArentStubs.html – blank 2013-02-15 10:13:16

+1

虽然你在你不妨阅读这个http://www.mockobjects.com/files/mockrolesnotobjects.pdf – blank 2013-02-15 10:21:18

+0

我希望你能赦免商业广告,但是我们写了一本完整的书“面向对象的软件”,解决了动机使用嘲笑。 – 2013-04-27 10:52:39

回答

19

正如我过去读过,这里是什么,我相信每个词代表

存根

这里你磕碰到已知值的方法的结果,只是为了让代码运行没有问题。例如,可以说你有以下几点:

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

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

所以,你最终做类似:

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

与你正在返回假数据,或创建一个对象的实例伪造假的。一个典型的例子是存储库类。采取这种方法:

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

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

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

然后,您可以将项目添加到fakeEmployees并断言预期的结果,在这种情况下,工资总额。

嘲笑

当使用模拟对象,你打算验证某些行为,或数据,这些模拟对象。例如:

要验证一个特定的方法是试运行期间执行,这是一个使用起订量嘲讽框架一般示例:

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/

+0

非常翔实。我一直认为假货和嘲笑是可以互换的。我每天都会在这里学习新东西:) +1 – bas 2013-02-15 11:20:45

+0

Mocks里有什么'm'?并且是我们正在测试的课程的东西? – fersarr 2015-08-19 09:54:12

+0

'm'是一个传递给'Expect()'函数的参数。这是一个lambda表达式。它不在任何地方声明,它只存在于'Expect()'lambda中。 'var mock = new Mock ();'表示你正在创建一个实现'ISomething'的对象,所以'ISomething'是一个接口,而不是一个对象。然后,您可以使用'mock'来控制方法在被调用时如何响应,例如通过'Expect()'函数。 – 2015-08-19 10:37:03

0

这个PHP单位手册帮了我很多的介绍:

“有时它只是普通的硬盘测试测试(SUT)的系统,因为它取决于在测试环境中无法使用的其他组件上,这可能是因为它们不可用,它们不会返回测试所需的结果,或者因为执行它们会产生不良的副作用;在其他情况下,我们的测试策略要求我们对SUT的内部行为有更多的控制或可见性。“更多:https://phpunit.de/manual/current/en/test-doubles.html

而我找到更好的“介绍”时,寻找“测试双打”作为嘲笑,假货,存根和其他人都知道。

3

它们都是测试倍数的变体。这里是一个很好的参考,说明它们之间的差异:http://xunitpatterns.com/Test%20Double.html

此外,从Martin Fowler的帖子:http://martinfowler.com/articles/mocksArentStubs.html

梅萨罗斯使用术语测试替身作为任何形式的 通称假装对象使用代替用于测试目的的真实对象。 这个名字来源于电影中特技双人的概念。 (其中一个 他的目标是避免使用已被广泛使用的任何名称。) 梅萨罗斯则定义了四个特定种类的双:

  1. 虚拟对象:围绕通过,但从来没有实际使用。通常他们 只是用来填充参数列表。
  2. 虚假对象实际上有工作的实现,但通常采取一些快捷方式,使得它们不适合生产(内存数据库是一个好的 示例) 。
  3. 存根提供测试过程中调用的罐装答案, 通常完全不会响应测试以外 中编程的任何内容。存根也可以记录关于呼叫的信息,例如 电子邮件网关存根,其记录它“发送”的消息,或者可能仅记录它“发送”的消息数量。
  4. 模拟是我们在这里谈论的对象:预先编程有预期的对象,它们构成了预期接收的呼叫的 规范。

在这些双打中,只有嘲讽坚持行为验证。其他双打可以并且通常使用状态验证。 Mocks 在练习阶段的表现与其他双打一样,因为他们需要让SUT相信它正在与其真正的 协作者交谈。