The microservices approach of building applications is most suitable when we develop complex applications with diverse functionalities. Since microservices, unlike monolithic architecture, keeps each function independent of the other, it is the most followed technique in modern times for large applications.
As per Mike Cohn’s pyramid, testing microservice is categorized into four different ways.
Following are the strategies that feature in testing microservice:
- End to end testing
- Integration testing
- Contrast testing
- Unit testing
Looking at the order of the testing pyramid, the most obvious question that comes to mind is, why unit testing forms the base of microservices testing?
A unit test is quite voluminous and is internal to the microservice. Ideally, this type of testing should be an automated process and depends upon the development language and the framework within the service.
Internationally renowned software engineer, Martin Fowler breaks unit testing into two categories.
Now let’s understand the two major components of unit testing.
Sociable & Solitary unit tests:
Sociable unit tests do not isolate the class under test and test class. While the solitary unit test does isolate the test class and class under test i.e, keeping outside of the scope. This can be the major difference between sociable and solitary tests.
Every deployed component in the microservice should have their defined unit tests within the code repository of the component. To minimize the complexity of different programming languages and frameworks used in the unit tests, it is advisable to select the suitable frameworks respective to the languages.
You are building a black-box environment when using a sociable test as the testing process will include class under test. The sociable approach is used for the business logic components that contain complex calculations and experience the state transitions. For example, an application working on real world problems and you need to deal with the frequent changes in the state of the component.
In simple terms, sociable tests include all of its collaborators and solitary tests exclude them and keep isolated.
For some testing purposes where test doubles can be used are, the cases where the solitary testing approach is taken even when the class under test has a collaborator. Here the class double can replace the collaborators for testing purposes.
Listing the test doubles types:
To avoid the most failures that are not related to the class under test but its dependencies, one can always isolate dependencies using solitary testing. Solitary testing is best known for its controlled pattern of test conduction approach.
Solitary testing is good at isolating the unnecessary components and are not needed for further testing and is the most beneficial in terms of speed and cost. Since it has test doubles to use, can replace the required components and more dedicated to optimise the time required for testing and ultimately saving the bucks.
Why Unit testing is important?
In a monolithic architecture, the applications contain features as a whole. Microservices takes one feature as a service and fulfill the goal of execution. Since there will be a separate microservice for a single business function, it is quite easy to test them in unit testing. Developers can achieve the utmost accuracy in software along with the massive cost reduction as compared to reworking and buggy applications.
Microservice and unit testing form a combined landscape of similar characteristic i.e., microservice works for single component/feature and unit testing works for testing individual components.
Unit testing helps QA engineers to keep the testing scope limited by limiting the testing of functionalities. That is the reason unit testing is less prone to failure. When combined with microservices, the ratio of successful test automation increases. Monolith architecture fails to recognize the errors in testing and goals are less scrutinized.
Microservices are decoupled into functions and you can change any module at any given time without affecting the entire application. And when you change and edit the microservice, you can give it to unit testing for checking the stability of small components and not the entire app.
You are opting for the best software quality when you combine microservices with the unit testing. Limited testing scope, fastest test runs with accurate results. Overall, this combination achieves the most business logic i.e., massive cost reduction, quick delivery, client satisfaction, and end-user bliss.
How to perform unit testing in microservices?
The figure shows different layers of microservices architecture (source.) Let’s see how do they work with unit testing?
Resources & Service layer:
Resources and services layer breaks down into two parts, collaborators and gateways. For the gateways residing at another server (which is almost always the case), using test doubles as mock objects should be preferable. You can do the solitary testing for the collaborators that slows down the process.
The domain logic contains calculations and state transitions so the objects are state-based, and hence, can not be isolated but the best choice is to do the sociable unit test.
A repository represents executing the queries and somehow is related to the database like an execution. For such a case, using a solitary test will work if integration tests are not worth performing.
Gateways are happened to connect with the external service and it is advisable to do a solitary unit test to avoid touching down the network.
Once you are ready for the unit test, take in the smallest possible code snippet of the AUT. The code snippet should perform the expected outcome and provide the right feedback to the development team. The more your unit tests are accurate and quick, the more you can be confident with your software deliverables.
Modern testing approaches like test automation and test-driven development take unit testing as the base of all testing types. Since it detects the errors from the small and get treated as quickly as possible.
From the above enumeration of the importance of unit testing it becomes easy to understand the reason as to why it forms the basis of the testing pyramid. After each microservice has been integrated with the application you cannot afford the cost of failure and its correction would be immense and unaffordable.
Hence, for testing applications designed with such an architecture be it automated or with the help of instructional documents, UNIT TESTING is inevitable when it comes to microservices.