Prabal Tripathi

A Mocked Test Is a Promise to Yourself

On end-to-end tests that fake the backend, and why they can never fail usefully.

There's a particular kind of test I've stopped writing: a browser test that fakes its own backend.

It's tempting every time. The real backend is slow, needs seeding, needs auth, and will occasionally be down for reasons that have nothing to do with you. You can replace it with a few lines that intercept every request and return the shape you want. The test goes green in seconds. It looks identical in the report.

It is close to worthless, and here's the specific reason.

What the test is for

Ask what a browser test is for. Not what it asserts — what job it does that nothing else does.

A unit test tells you a function is correct. A type checker tells you the shapes line up. Neither can tell you that the frontend and the backend still agree with each other. Only something that drives both at once can.

That's the entire value proposition. It's the one failure mode nothing else catches.

What mocking removes

When you mock the backend, you encode the frontend's belief about the response into the test. Now the test asserts that the frontend agrees with itself.

So when someone changes the API — renames a field, changes a status code, makes a list paginated — your test stays green. It will always stay green. It cannot do otherwise, because the thing it talks to is a fiction you wrote.

The real end-to-end test lives in the frontend repo but fails in the backend pull request that breaks the flow. That's the protection you're buying. Mock it away and the regression ships, and nobody finds out until a user does.

The cost argument, which cuts the other way

"But the mocked one is cheaper." Is it?

The pipeline spins up a browser, a runner, a container, either way. You pay the same compute. The mocked run produces something a unit test could have produced for a fraction of the cost. You've paid end-to-end prices for unit-test information.

If you're going to spend it, spend it on the only thing this lane can do.

Where mocks are fine

Rendering edge cases. An error state the backend produces once a year. A loading skeleton. Things where the point is the UI's reaction to a shape, and you're not claiming the shape is real.

That's a legitimate lane. Just don't let it count as coverage of a flow.