TDD Mocking - 指定模拟对象行为白盒测试?

Mar*_*tin 9 tdd mocking

我最近刚开始使用TDD,在阅读了Kent Beck关于测试驱动开发的书之后,我脑子里仍然有很多关于测试设计的问题.

我目前遇到的一个问题是使用Mock对象.下面是一个非常简单的生成报告:

public string MakeFinancialReport()
{
    return sys1.GetData() + sys2.GetData() + sys3.GetData();
}
Run Code Online (Sandbox Code Playgroud)

报告必须包含标题,正文和页脚.因此,快速测试报告中是否存在这些标题:

public void TestReport()
{
    string report = MakeFinancialReport();
    Assert.IsTrue(report.Contains("[Title]") && report.Contains("[Body]") && report.Contains("[Footer]"));
 }
Run Code Online (Sandbox Code Playgroud)

为了隔离方法,我想我会嘲笑sys1,sys2和sys3调用.现在,如果他们都是嘲笑,我还有什么可以测试的?此外,当我模仿它们时,为什么我必须告诉模拟对象它们将被调用一次并返回X等.如果它不仅仅是一个黑盒测试而且MakeFinancialReport可以调用尽可能多的调用它想建立报告?

我对这个小问题感到困惑,我不确定我错过了什么.我认为Mocking可以删除可测试的代码,对于大多数简单的方法,剩下要测试的内容根本没用.

Don*_*kby 2

仅当模拟对象有用时才应使用它们。如果MakeFinancialReportsys1sys2sys3都具有复杂的逻辑,那么您需要独立测试它们中的每一个。通过提供三个sysX对象的模拟版本MakeFinancialReport,您可以消除它们的复杂性并进行测试MakeFinancialReport

当您想要测试错误条件和异常处理时,模拟对象特别有用,因为可能很难从真实对象中强制发生异常。

当您谈论不必设置明确的期望和返回值时,这是一个称为存根的相关概念。您可能会发现 Martin Fowler 的“模拟不是存根”很有帮助。

Kent Beck 的书是一个很好的介绍,但如果您正在寻找更多细节,我强烈推荐xUnit Patterns 一书。例如,它有一个关于模拟对象的部分,以及更一般的测试双打类别。

  • 在您的示例中,@Martin,剩下的就是字符串连接。这没什么需要测试的。如果没有什么可测试的,那么这就是一种代码味道,会促使您进行“内联方法”重构。也许你应该寻找一个更好的例子。 (2认同)