Rough Work/the guardrails

Mocking at the Boundaries

Mocks are a polarizing topic. Use too many, and your tests become "hallucinatory" — they pass in a world where everything is perfect, but the actual app fails because you mocked out reality. Use too few, and your tests become slow, flaky, and dependent on a working internet connection.

Mock across boundaries, but not within them.

Within your application's core business logic, avoid mocks. Let your domain objects talk to other real domain objects. If your Order logic depends on your Pricing logic, use the real pricing engine. Mocked domain objects can drift from each other silently — each test passes against a version of the other component that no longer reflects how it actually behaves, and the real integration breaks in ways no test predicted.

But when you hit the boundary of your system — the database, an external API, the file system — that's where mocks earn their place. Your tests shouldn't fail because a third-party payment gateway is down for maintenance. The goal is to test how your code handles the response from that gateway, not the gateway itself.

Real objects for the things you own. Mocks at the edges.

to navigate