在执行 TDD 时,何时实现新的模拟依赖项?

While doing TDD, when to implement a new mocked dependency?

提问人:Unknown Id 提问时间:4/15/2016 最后编辑:Dave SchweisguthUnknown Id 更新时间:5/11/2016 访问量:274

问:

有一个问题我找不到答案,关于由外而内的TDD:

我实现了一个新单元 (A),为它编写了一个测试,这个单元需要一个尚不存在的依赖项 (B)。在我的测试中,很容易模拟这种依赖关系,但是我在生产代码中该怎么做?

我是否先实现 (B) 并让我的 (A) 测试失败,同时因为我还没有继续实现它以使其测试通过?

还是我先完成 (A) 并同时让 (B) 的测试失败,因为它只是返回“空”对象,而不是实际执行其规范告诉它做的事情?

或者我应该让 (B) 的测试在我继续实现 (A) 时暂时检查它是否返回“空”对象 - 尽管这实际上不是 (B) 的规范?

单元 测试 与语言无关的 模拟 TDD BDD

评论


答:

3赞 Dave Schweisguth 4/15/2016 #1

TDD 的基本策略是让所有测试都通过,除了你现在正在做的测试。在你担心(B)之前,让(A)的测试通过。

为类 (A) 及其复杂依赖项 (B) 编写测试和代码的顺序为

  • 为 (A) 编写一个测试。[套房是红色的。
  • 开始实现足够多的 (A) 以使您刚刚编写的测试通过。发现您需要 (B)。[套房是红色的。
  • 模拟 (B)。[套房是红色的。
  • 完成您刚刚编写的 (A) 测试通过。 [套件为绿色。啊!重构。
  • 如果您还没有到达 (A) 的良好停止点,请返回顶部并重复,直到您处于 (A) 的良好停止点。
  • 为 (B) 编写一个测试,要求 (B) 完成 (B) 模拟的部分或全部操作。[套房是红色的。
  • 让你刚才写的测试通过。 [套房是绿色的。啊!重构。
  • 如果您还没有复制 (B) 模拟在测试和代码中执行的所有操作,请返回两步并重复,直到您复制了 (B) 模拟执行的所有操作。

在这一点上,你可以选择在(A)或(B)上做更多的工作,或者开始一些新的事情。

尽管此策略使测试始终通过,但它并不能确保应用程序立即执行有用的操作。确保你的应用程序最终做一些有用的事情的方法不仅仅是 TDD:首先编写一个验收测试(在没有模拟的情况下针对整个应用程序运行)和 TDD,直到验收测试和单元测试都通过。

验收测试(或其他集成测试)还可以确保在模拟类的测试和代码中正确复制模拟。

另请注意,跟踪您已经想到但尚未实现的需求,或者您仅在模拟中“实现”并且需要在模拟依赖项的测试和代码中实现的需求至关重要。这就是为什么 TDD By Example 和其他 TDD 如何完成的例子如此多地谈论实际或心理待办事项列表。对于具有模拟依赖项 (B) 的类 (A),在编写模拟后,您可以返回 (A) 或在 (B) 中实现您刚刚对模拟执行的操作。无论哪种方式,你都必须跟踪你选择做的事情,直到你准备好回去做。

0赞 Igor Fil 4/16/2016 #2

我建议只有在代码中真正需要 B 时才依赖 B。如果 A 中没有任何东西依赖于 B,为什么要在这个阶段添加它?

如果你的代码现在真的需要 B,为什么不开始实现你现在需要的 B 功能呢?

当然,如果代码中没有任何逻辑,您也可以在代码中使用虚拟对象而不是 B。否则,我将开始实现 B。