单元测试模式

use*_*078 5 unit-testing design-patterns

我正在寻找以下单元测试用例的解决方案/模式.

案子:

让我们假设我们有三个类,A,B,C,每个类都有一个方法.A的方法调用B的方法,该方法调用C的方法.所以,A-> B-> C. 每种方法都采用一个输入(方法A的输入A,输入B,输入C).对方法A的调用的结果输出将是树结构,例如:

Root(从方法A创建) - 节点B(从方法B创建) - 节点C1 - 节点C2(都是从方法C创建的)

对我来说,单元测试是关于单独测试方法输入的输出.因此,我们将为上述每种方法编写单元测试.因为测试是单独编写的,所以我们在编写方法A的单元测试时模拟方法B,并在编写方法B的单元测试用例时模拟方法C.

到目前为止,一切都很好,我们可以在每个方法的输出上写下期望,以确保产生的树结构得到尊重.

问题:

现在让我们添加另一个类,它将调用方法B,以便我们也有以下调用链:D-> B-> C. 生成的根树将如下所示:

  • 根D
    • 节点B.
      • 节点C1
      • 节点C2

在开发过程中,有人意识到方法A的要求被误解了,树结果应该是这样的:

  • 根A
    • 节点B.
      • 节点C.

令人高兴的是,开发人员将更改方法C,以便输出仅返回一个节点而不是两个节点.他会改变单元测试,以便反映这些变化.但是,方法D要求不应该改变,并且该方法的输出应该仍然具有节点C1和节点C2.

问题:

您将如何编写单元测试,以便第二个开发人员可以提醒他为方法D引入的更改?我宁愿避免在这里看起来最合适的集成测试.

谢谢.

gui*_*e31 0

如果您想坚持使用独立的单元测试(我对大多数中心对象都这样做,因为我发现几乎不可能以正确的深度编写正确数量的集成测试并保持它们快速),一个有趣的方法是 Joe Rainsberger 的Contract和协作测试。他提出了这样的观点:您不应该模拟依赖项以在测试中以某种方式运行,除非您有相应的契约测试来确保该依赖项的具体实现在现实世界中确实以这种方式运行。

在您的示例中,说“方法 C 现在仅返回一个节点而不是两个”意味着相应地更改 C 的合约及其合约测试。这引入了模拟 C 与新合约不同步的可能性,因此您应该在测试中查看 C 被模拟的所有地方,并在需要时调整模拟。

在仔细检查现有测试之后,您会意识到您并不是真的想更改方法 C 的约定,而是引入适合 A 需求的新方法 C2。

Rainsberger 描述了他用来确保在测试中实现互惠的过程您还可以在此视频中观看该技术的实际运用。