【问题标题】:While doing TDD, when to implement a new mocked dependency?在进行 TDD 时,何时实现新的模拟依赖项?
【发布时间】:2016-04-15 09:48:35
【问题描述】:

关于采用由外向内方法的 TDD,有一个问题我找不到答案:

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

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

或者我是先完成(A),同时让(B)的测试失败,因为它例如只是返回“空”对象,而不是实际执行规范要求的操作?

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

【问题讨论】:

    标签: unit-testing testing language-agnostic mocking tdd


    【解决方案1】:

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

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

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

    此时,您可以选择在 (A) 或 (B) 上多做一些工作,或者开始新的工作。

    尽管这种策略可以让您的测试始终通过,但它并不能确保您的应用程序立即执行一些有用的操作。确保您的应用程序最终做一些有用的事情的方法超越了 TDD:首先编写一个验收测试(它在没有模拟的情况下针对整个应用程序运行)和 TDD,直到验收测试和您的单元测试全部通过。 (更多信息请参见。)

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-04
        • 2017-03-22
        • 1970-01-01
        • 2019-08-08
        • 1970-01-01
        相关资源
        最近更新 更多