100% Unit Testability in Hexagonal Architecture
January 4, 2022
Blog > Hexagonal Architecture, Quality, TDD, Unit Testing | Valentina Cupać
100% Unit Testability in Hexagonal Architecture
Let’s go back in time… to the “traditional” 3-layered architecture. Here, we implement the business logic layer (which directly references the database layer). In this case, we cannot run the application without the database! It also means we cannot unit test this application. So we have the problem of LOW TESTABILITY.
This is where Hexagonal Architecture comes to the rescue. Alistair Cockburn that the intent is to “Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases.” The beauty of Hexagonal Architecture is that it is built with HIGH TESTABILITY in mind. How? Through strong ISOLATION.
INTERNAL WORLD (The “inside”)
Hexagon: The “internal world” is application itself. We want to keep the “internal world” uncontaminated, we don’t want it to be affected by the “external” world. We can think of this as a capsule, called a “Hexagon”.
Driver Ports (User-side API): Our application exists so that it helps clients to run some use cases – clients can be human users, other programs, test harnesses… We want to expose ONLY the use cases to the clients (and NOT expose the internals of the application!). So the Hexagon provides some kind of client-facing API (“driver” ports), so that our clients can execute the use cases.
Driven Ports (Server-side API): On the other hand, our application may need some mechanism to persist data, or perhaps to send some notifications, or any other kind of communication with external systems. In this case, we don’t want to directly talk to those external systems, we use interfaces as an abstraction layer.
Note: To make it easier to remember the words “Driver” and “Driven”, here’s how I remember: Users are the drivers of our application. External systems that we need to talk to are driven by our application.
EXTERNAL WORLD (The “outside”)
Driver Adapters (User-side adapters): The driver adapter presents the application in some way suitable for consumption – it could be as a GUI, a REST API, a SOAP API, a Console App, and then it calls the driver port.
Driven Adapters (Server-side adapters): The driven adapter implements the driven port. So for example, if we had a driven port for database access, then we could have an adapter for the MySQL database; if we had a driven port for sending notifications, then we could have an Email Notifier adapter.
100% TESTABILITY
Hexagonal architecture makes our entire Application Core (the Hexagon) 100% unit-testable! How?
– We can execute the use cases through driver ports (user-side API)
– We provide test doubles to implement the driven ports (server-side API)
This ISOLATION enables us to fully unit test our use cases!
References: https://lnkd.in/d4pBs_br