单元测试更大的单元
上一节介绍了用 测试替身(test doubles)围绕领域模型的每个端口进行测试的想法。这为我们提供了一些有趣的机会,可以在本节中讨论。我们可以测试像用户故事一样大的单元。
我们熟悉的单元测试通常是针对小规模代码的测试。你可能听过有人说,单元测试应该只应用于单个函数,或者每个类应该为每个方法编写一个单元测试。我们已经看到,这并不是使用单元测试的最佳方式。这样的测试会错过一些优势。更好的做法是将测试视为覆盖行为,而不是实现细节。
结合六边形架构设计和测试行为(而非实现细节)的方法,带来了一种有趣的系统分层方式。与传统的三层架构不同,我们有一系列逐渐更高级别的行为圈。在我们的领域模型中,我们会发现那些小规模的测试。但随着我们向外移动到适配器层,我们会发现更大的行为单元。
单元测试完整的用户故事
领域模型中的端口形成了领域模型的自然高层边界。如果我们回顾本章所学的内容,我们会发现这个边界包括以下内容:
-
用户请求的本质
-
应用程序响应的本质
-
数据存储和访问的本质
-
所有使用无技术细节的代码
这一层是我们应用程序所做事情的本质,摆脱了如何实现这些事情的细节。它正是原始用户故事本身。关于这个领域模型最重要的一点是,我们可以针对它编写 FIRST 单元测试。我们拥有用简单的测试替身替换难以测试的外部系统所需的一切。我们可以编写覆盖整个用户故事的单元测试,确认我们的核心逻辑是正确的。
更快、更可靠的测试
传统上,测试用户故事涉及在测试环境中进行较慢的集成测试。六边形架构使单元测试能够取代其中一些集成测试,从而加快我们的构建速度,并提供更高的测试可重复性。 |
我们现在可以在三个粒度上对领域模型进行测试驱动:
-
针对单个方法或函数
-
针对类的公共行为及其任何协作者
-
针对整个用户故事的核心逻辑
这是六边形架构的一大优势。与外部服务的隔离将用户故事的核心逻辑推入领域模型,使其与端口交互。正如我们所看到的,这些端口——通过设计——非常容易编写测试替身。值得重申 FIRST 单元测试的关键优势:
-
它们非常快,因此测试我们的用户故事也会非常快
-
它们高度可重复,因此我们可以信任测试通过或失败的结果
当我们用单元测试覆盖广泛的功能区域时,我们模糊了集成测试和单元测试之间的界限。通过使测试更容易,我们消除了开发人员测试更多用户故事的障碍。使用更多的单元测试可以改善构建时间,因为测试运行速度快并提供可靠的通过/失败结果。需要的集成测试更少,这是好事,因为它们运行速度较慢且更容易产生不正确的结果。
在下一节中,我们将把所学知识应用到我们的 Wordz 应用程序中。我们将编写一个端口,抽象出为用户获取猜测单词的细节。