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.