Testingintermediate
Integration Testing vs Unit Testing
The distinction between testing units in isolation with mocked dependencies versus testing how multiple real components work together, and the tradeoffs of each.
The difference is how much is real.
Unit testing is like a car manufacturer bench-testing each individual part (the engine, the brakes, the transmission) separately on isolated test rigs to confirm each one works correctly on its own. Integration testing is actually bolting several of those real parts together into a partially assembled vehicle and driving it around a test track, confirming the engine's real power actually reaches the real wheels correctly through the real transmission, not just that each part individually performed fine in isolation.
Key Concepts
1
unit one function or module; dependencies faked
integration several real pieces together -- a service and a
real database, a route and its handlers
end to end the whole system through the user interface2
The trade is speed against confidence.
unit milliseconds. Precise failures. Proves little
about the whole.
integration seconds. Proves the pieces fit.
end to end minutes. Proves it works. Fails vaguely, and
flakes.3
Where unit tests mislead. Both sides can be individually correct and wrong together:
4
// unit test: the service calls repo.save
// unit test: the repo saves correctly
// and the service passes the arguments in the wrong order5
Every unit test passes. The feature is broken. Only a test using both catches it.
6
Which is why the shape of a suite matters more than the count. Many fast unit tests for logic, a solid
layer of integration tests for the seams, and a few end-to-end tests for the critical journeys.
7
The integration tests are the ones most often missing, and they are where the highest-value bugs are:
serialisation, database constraints, transaction boundaries, and the contract between modules.
8
Make them realistic.
a real database in a container, not an in-memory substitute
the real HTTP layer, not the handler called directly
real serialisation9
An in-memory database with different constraint behaviour is the case where a test passes and production
fails on the same code.
10
Keep them isolated. Each test creates its own data and cleans up, or runs in a transaction rolled back
afterwards. Shared fixtures produce tests that pass alone and fail in CI, which is the most expensive kind
of flake.
11
The judgement to state. The test pyramid is a guideline, not a rule. A system that is mostly
orchestration — services calling services — gets little from unit tests and a great deal from integration
tests, because the logic is in the connections rather than inside any one piece.
12
What the interviewer is probing.1. "What does an integration test catch that unit tests cannot?" Probing: the gap. Stalls:
"Bigger bugs." Moves up: the wiring — two correct units with an incompatible contract between
them, which no unit test can see.
13
2. "What is the trade?" Probing: the cost. Stalls: "They are slower." Moves up: slower,
more setup, and a failure localises less precisely — so you want many unit tests and fewer
integration tests.
14
3. "Where should the boundary sit?" Probing: judgement. Stalls: "Per class." Moves up:
around a behaviour rather than a file — testing a use case through its entry point often beats one
test per class.
15
4. "What is the test pyramid?" Probing: the shape. Stalls: "A rule." Moves up: many fast
unit tests, fewer integration tests, very few end-to-end — because cost and flakiness rise as scope
grows.