Unit Test vs Integration Test

Testing parts vs testing the whole

Unit tests and integration tests serve complementary roles in a testing strategy. Unit tests verify individual components in isolation, while integration tests verify that multiple components work correctly together. Both are essential for software quality.

Unit Test

A unit test verifies the behavior of a single, isolated unit of code — typically a function, method, or class. Dependencies are replaced with mocks, stubs, or fakes so the test focuses exclusively on the logic under test. Unit tests are fast (milliseconds each), deterministic (no external dependencies), and numerous (a mature project may have thousands). They're the foundation of the testing pyramid. Unit tests excel at catching logic errors, validating edge cases, and enabling confident refactoring. Frameworks like Jest, pytest, JUnit, and Go's testing package make unit testing straightforward.

Integration Test

An integration test verifies that multiple components work correctly together — the 'integration points' between units. This might mean testing a function with a real database instead of a mock, testing an API endpoint end-to-end, or verifying that two microservices communicate properly. Integration tests are slower than unit tests (they involve real I/O), more complex to set up (you need databases, queues, or services running), and fewer in number. But they catch a critical class of bugs that unit tests miss: serialization errors, database query issues, API contract violations, and configuration problems.

Key Differences

- **Scope**: Unit tests cover a single function or class. Integration tests cover the interaction between multiple components. - **Dependencies**: Unit tests mock external dependencies. Integration tests use real dependencies (databases, APIs, file systems). - **Speed**: Unit tests run in milliseconds. Integration tests can take seconds or minutes due to real I/O. - **Failure diagnosis**: Unit test failures pinpoint the exact broken function. Integration test failures require more investigation to find the root cause. - **Quantity**: The testing pyramid recommends many unit tests and fewer integration tests. - **Setup complexity**: Unit tests need minimal setup. Integration tests often need Docker containers, test databases, and seed data.

When to Use Each

**Write unit tests** for business logic, algorithms, data transformations, validators, and any pure functions. They should be your first line of defense and run on every commit. **Write integration tests** for database queries, API endpoints, authentication flows, third-party service interactions, and any code where the integration between components is the risky part. They typically run in CI/CD pipelines and catch issues that unit tests structurally cannot.

Analogy

**Unit tests** are like testing each car part individually on the factory floor — verifying the engine starts, the brakes grip, the steering wheel turns, and the headlights shine. **Integration tests** are like taking the assembled car for a test drive — the engine works, the brakes work, but do they work together? Does pressing the brake pedal actually trigger the brakes, or was the cable connected wrong?