Earlier, we discussed the thumb rules of unit testing.
Unit tests form the first level in the Test Pyramid - we achieve faster results by assuming behaviour for all external boundaries.
Integration tests are a step ahead - they sufficiently test the communication over these external boundaries.
Here are 3 things developers should keep in mind while writing integration tests.
Allow integration tests to be narrow.
Integration tests validate if two separately developed units work well together.
We can allow integration testing to be white-box if we test each integration point at a time.
Example: An application interacts with a database and an external API service.
Integration testing for database interaction -
Start a database.
Invoke the code that performs database operations.
Validate the operations were successful.
The integration test can mock all other external interactions as it only tests database interactions.
Narrow integration tests test for one integration point at a time.
We don't need to initiate an entire stack to run integration tests if they are narrow.
All external services should be set up locally so that integration tests can be run during the development phase and reduce any operational hassles.
A local setup makes integration tests fast and easy to run - they can be added to the build pipeline with ease.
Example: A single deployment file that spins up services on your laptop using an orchestrator such as "docker".
A local setup makes integration tests more deterministic - we remove network failures.
External services don't always imitate exact behaviour in a local environment.
The local instance could be unofficial or mismatch the latest versioned behaviour.
In such a case, we should opt for mocking the service at the last level of interaction by using appropriate test doubles.
These test doubles guarantee that the public interfaces work as expected.
Narrow integration tests validate clients not servers.