Hexagonal 中的 InboundPorts 如何提高可测试性

How InboundPorts in the Hexagonal increase testability

在端口和适配器(六边形)架构中,您有:

DrivingAdapter -> InboundPort <- [ domain ] -> OutboundPort <- DrivenAdapter

注意:端口当然是域的一部分

一个具体的例子可以是:

WebController -> OrderServicePort [ order domain ] -> OrderRepositoryPort <- MongoDbOrderRepositoryAdapter

因此,端口和适配器架构背后的想法是,将您的域与应用程序边缘的具体适配器分开测试。

我不明白的是,在左侧公开接口端口对可测试性有何帮助?

WebController 没有重要的逻辑,因此本身不是测试目标,而是作为端到端测试的一部分进行测试。所以我不会嘲笑 OrderServicePort,因为它通常是我的测试对象。

当然 InboundPorts 的价值在于它们只公开了实现它的具体域 class 的简化视图。

但我看不出使用 InboundPorts 增加的可测试性来自何处。

同意吗?

TL;DR;

是的,我同意。


我将端口视为一个抽象概念,与语言结构无关。我的意思是端口并不意味着接口,甚至可能不需要接口。在某些语言中甚至没有接口,因此需要使用其他语言结构来完成移植。

我也看到 primary/driving(入站)端口和 secondary/driven(出站)端口作为具有不同具体目标的工件,尽管共享相同的想法作为一个 entry/exit 点来自应用核心。

在我看来,辅助端口是 "prototype" 核心需要的工具,以它需要的方式。在许多情况下,此 "prototype" 只是一个接口,但始终将其视为接口是有局限性的。辅助适配器将是该端口的具体实现,环绕着一个库。这很强大,因为它可以很容易地交换所使用的库,无论是为了测试还是为了方便。

但是,主端口是应用程序的入口点,它启动一个用例,它告诉应用程序要做什么以及如何做。它是具体的东西,而不是原型。它是应用程序的核心。所以如果我们替换它,我们就是在替换应用程序核心本身。主要端口不像次要端口那样是原型,因此,就其本身而言,它不需要类似接口的东西。

替换它的唯一原因是测试主适配器本身,只是为了确保它们指向正确的用例。在这种情况下,我们需要类似接口的东西。但在这种情况下,无论如何我们都需要启动应用程序,这通常是最昂贵的部分或测试,因此我们不妨将其作为端到端、功能或集成测试来进行,我们还测试核心或部分它。

在某些语言、应用程序或上下文中,在某些边缘情况下,也许需要这样做,也许这是最好的方式。我们不应该说像 "never do ..." 或 "always do ..." 这样教条的东西,它总是取决于上下文。

但是,总的来说,我同意你的观点:主端口上的接口对测试没有太大的好处,我会进一步说主端口不需要接口。

完全不同意

驱动端口在六边形架构的可测试性中非常重要,它们是一个关键概念。

驱动程序端口是 "hexagon" 的 API("hexagon" = "business logic" = "application")。它们是用例(transacional)边界,六边形的左边缘。

当您单独测试六边形时,您 运行 针对这些端口测试(驱动程序适配器),并且您 "mock" 驱动端口。

如果您没有 API 六边形行为(功能),您将如何测试该行为?您测试 API(驱动程序端口)。它们是 SUT 行为的契约。

更重要的是,当您 运行 将测试作为回归测试时,它们可以让您检测业务逻辑泄漏。

另一个有用的东西是它们可以让你实现一个硬编码的六边形。

看到这个:

https://jmgarridopaz.github.io/content/hexagonalarchitecture.html#tc6-1-1