How to test without mocking
Role of mocking
- Many see mocks as a useful tool to isolate a “unit” from its dependencies, make tests deterministic, and express specific scenarios (including error paths).
- Others argue mocks are often misused: tests end up asserting on mocks rather than behavior, or mirroring the implementation, making them brittle and low-value.
- A recurring criticism: mocks rarely cover real edge cases; they model a “happy path” view of dependencies, so they miss bugs that occur with real systems.
Databases and I/O
- Strong sentiment that mocking databases is usually a footgun. Real databases (often via Docker/TestContainers) are now easy enough to run and better reflect production behaviors (transactions, isolation, collation, triggers, performance).
- Various strategies discussed: per-test schemas or databases, wrapping tests in transactions and rolling back, seeding via SQL fixtures or helper code, using anonymized production dumps, and even snapshotting production replicas.
- Some note managed DBs (e.g., cloud offerings) can differ from local instances, so tests must align with the actual runtime environment.
Third‑party APIs and failure cases
- For complex or rate‑limited external APIs, mocks or recorded responses (e.g., VCR‑style tools) are seen as necessary to avoid instability, cost, and rate limits.
- Others report success running E2E tests directly against real sandbox APIs, with few issues.
- Mocks/fakes are widely viewed as the most practical way to test rare or hard‑to‑trigger failures (HTTP 500s, timeouts, malformed data, payment gateway quirks).
Test strategy and layering
- Broad agreement that no single style is sufficient: combine unit tests (often with mocks/fakes) with integration and E2E tests (real dependencies).
- Several reference the testing “pyramid” and suggest prioritizing integration/E2E if time is limited, while still valuing targeted unit tests for quick diagnostics.
Design, testability, and documentation
- Heavy reliance on mocks is seen by some as a design smell: indicates poor separation of logic and I/O, excessive statefulness, or tight coupling.
- Dependency inversion and clear boundaries can reduce the need for mocks, or shift toward simpler fakes/data-driven tests.
- Debate over whether unit tests primarily serve as regression guards, executable documentation, or bug-finding tools; most agree they do some of each.
Overall view of the article’s claim
- Many commenters consider “mocking is an anti‑pattern” overly absolutist and misleading.
- Consensus trend: mocking has real costs and is often overused, but remains valuable in specific contexts; “it depends” and good judgment matter more than blanket rules.