How to Migrate From Monolithic Applications to a Microservice Architecture: Part 3
Continuous delivery and confidence in testing
One of the primary goals of our recent redesign of the edocr document application was to continue our progress towards a continuous delivery system and away from a model of scheduled maintenance windows and releases that is tied to sprints.
As mentioned in the previous post in this series, testability of our product is one of the core reasons that edocr is in the process of being moved to a microservices architecture. The ability to feel comfortable with the scope and potential impact of changes to any particular piece of the application is paramount to achieving a low-friction continuous delivery system.
Small, easily refactored components—provided by default in any well-built microservices project—are much easier to write unit tests for and achieve your team’s desired level of code coverage. With a more traditional application approach, there are quite often numerous dependencies that must be mocked for the unit testing of any given class or module. Relying on the well-defined separation between services that communicate via HTTP allows any necessary mocks to follow a well-defined communication protocol over JSON and not have to be custom written in each case for the specific interface. Good service design lends itself naturally to good testable code patterns, and that improves the reliability and refactorability of your codebase.
Automated integration tests
Likely more important to continuous delivery is the suite of black-box user-centered tests that ensure any changes, refactors, or optimizations made during development have not caused regressions in the user experience. While all systems benefit from end-to-end automated tests, the microservice architecture allows for the application to be tested in layers. Below is an example of the automated tests that can be implemented for our application prior to the update and now. While the most important tests will often be those that simulate the user experience via the user interface, it is much easier to pinpoint the cause of issues when each service can be tested directly via the exposed HTTP interface. As an added benefit, once the offending code is located in one of the numerous services, it should, by design, be easier to review and adjust to get the direct automation working.
One end result of re-architecting our application to a system of independent microservices is that we have the ability to greatly improve the confidence in our testing and leverage that confidence to speed up the rate of delivery for new features and bug fixes.