The hardest part of frontend testing isn't writing the test. It's getting the backend to return the exact response you need: a 500, an empty list, a malformed payload, right when you want it. On a live server that's painful, and sometimes impossible.
Here's the workflow I use instead. I make the app receive any response I want, without touching the backend at all. Postman mock servers do the heavy lifting, and an AI fills them with data.
The idea: a fake backend that looks real
Your frontend doesn't know where the JSON comes from. It calls a URL and trusts whatever comes back. So you point it at a mock server: a fake address that returns responses you defined in advance. Same endpoints, same shapes, zero real backend.
Why not just DevTools or a proxy?
For a quick one-off, browser tools are fine:
- Chrome DevTools, Local Overrides rewrite a response right in the browser.
- Charles / Requestly / mitmproxy intercept and swap responses on the fly.
But the override dies when you close the tab, it lives only on your machine, and you can't hand it to a teammate or a CI pipeline. For anything beyond a single check, you want a real, persistent stand.
Step 1: build the collection
In Postman you already (or soon will) have a collection: the same endpoints your real API exposes, with method, URL, body and headers.
Step 2: add example responses
For each request, hit the three dots and pick Add example. An example is a saved response: a status code plus a body. You write it by hand.
Hang several examples on the same endpoint to cover every case:
-
200success -
404not found -
[]empty list -
500server error
Step 3: spin up the mock server
Three dots on the collection, then Mock collection. Postman gives you an address:
https://xxxx.mock.pstmn.io
Step 4: point the frontend at it
Swap the base URL in your app config:
- const API = "https://api.production.com"
+ const API = "https://xxxx.mock.pstmn.io"
That's it. Your frontend now talks to the mock and never notices the difference.
One endpoint, every scenario
Here's where it gets good. You hung 200, 404 and 500 on the same endpoint. Which one does the mock return? It decides by a request header:
x-mock-response-name: order not found
Send that header from your automated test, and a single endpoint runs through every scenario without touching the server or the data:
await fetch(`${API}/orders/42`, {
headers: { "x-mock-response-name": "server error" }
})
// the mock returns your 500 example
Responses don't have to be static
Postman supports dynamic variables right inside the example body:
{
"id": "{{$randomInt}}",
"name": "{{$randomFullName}}",
"email": "{{$randomEmail}}"
}
Every call comes back with different data instead of one hardcoded blob, so you catch the bugs that only surface on unexpected input.
The part that saves the most time
Writing dozens of example responses by hand is the boring tax on all of this. So I don't.
I hand the whole collection to Claude through the Postman MCP, and it generates the example responses for every endpoint (success, edge cases, malformed payloads) and wires up the mock. I'm not asking it to write code. I'm asking it to assemble a working test stand while I drink my coffee.
That's the shift: AI stopped being "write me this function" and became "build me the tool".
How do you handle this on your team: Postman mocks, a standalone mock service, or still waiting on the backend?
Top comments (0)