A DELETE endpoint that returns 204 No Content and deletes nothing will pass every single-request test you write.
The status code is right. The response time is fine. The body is empty, as specified. Your suite is green — and the record is still in the database, because the only way to know deletion worked is to ask again: a follow-up GET that must return 404.
That's the behaviour layer of API testing, and it can't be reached one request at a time. It needs chained requests — a sequence where each step feeds the next, testing the resource's whole lifecycle. In Postman the bridge between steps is one line of script. Here's the full pattern.
The bridge: capture, then reference
Everything hangs on one move — capture a value from a response, use it in the next request's URL or body.
Request 1 — POST /users (Scripts → Post-response):
pm.test("User created", () => pm.response.to.have.status(201));
const created = pm.response.json();
pm.collectionVariables.set("newUserId", created.id);
Request 2 — GET {{baseUrl}}/users/{{newUserId}}:
pm.test("Created user is retrievable", () => {
pm.response.to.have.status(200);
pm.expect(pm.response.json().id)
.to.eql(pm.collectionVariables.get("newUserId"));
});
Run the collection (the Runner executes top to bottom) and the two requests are now one test: creation actually persisted.
Why pm.collectionVariables and not pm.environment? The captured ID is run-state, not configuration — it belongs to the suite, not to "staging vs production". Keeping run-state in collection scope also means the chain works no matter which environment is selected.
The full lifecycle chain
The canonical workflow folder — five requests, each verifying the last:
📁 User lifecycle
1. POST /users → 201, capture newUserId
2. GET /users/{{newUserId}} → 200, fields match what was sent
3. PATCH /users/{{newUserId}} → 200, capture nothing, send {"name": "Updated"}
4. GET /users/{{newUserId}} → 200, name is "Updated", other fields unchanged
5. DELETE /users/{{newUserId}} → 204
6. GET /users/{{newUserId}} → 404 ← the test that actually proves deletion
Step 4 deserves its subtle assertion: not just that the patched field changed, but that the others didn't — PATCH endpoints that quietly reset unrelated fields are a classic, expensive bug:
const user = pm.response.json();
pm.test("PATCH changed only the name", () => {
pm.expect(user.name).to.eql("Updated");
pm.expect(user.email).to.eql(pm.collectionVariables.get("originalEmail"));
});
(Capture originalEmail back in step 1, same one-liner pattern.)
Fresh data every run
A chain that creates test@example.com works exactly once against a persistent database — the second run collides with the first run's leftovers. Postman's dynamic variables fix this with zero code:
{
"name": "{{$randomFullName}}",
"email": "{{$randomEmail}}",
"ref": "{{$guid}}"
}
Every run creates unique records. And the companion discipline: tests that create data should delete it — which the lifecycle chain does by design, steps 5–6. A suite that cleans up after itself is a suite you can run any time, from anywhere, including every 15 minutes from CI. Re-runnability is the cardinal virtue of automation.
Controlling the flow
By default the Runner goes top to bottom. Scripts can redirect it:
// Skip to teardown if creation failed — no point testing a ghost
if (pm.response.code !== 201) {
pm.execution.setNextRequest("Cleanup");
}
// Or end the run entirely
pm.execution.setNextRequest(null);
(postman.setNextRequest is the legacy name; pm.execution.setNextRequest is current.) Use it sparingly — a suite that jumps around is hard to read — but skip-on-failure and polling loops are exactly what it's for.
Keep chains short
One warning from maintenance experience: chains are powerful and chains are coupling. A folder where request 6 depends on request 1 is fine; a collection where request 40 depends on request 3 is unmaintainable. The discipline that scales: each workflow folder is self-contained — it creates what it needs, verifies behaviour, and destroys what it made. Folders can run independently; requests within a folder cannot. That's the right amount of coupling.
Adapted from Chapter 7 of my free, open-source book *API Testing Using Postman: The Practical Guide to Modern API Testing*. Read online, grab the PDF/EPUB, or contribute on GitHub.
I'm a PhD researcher in Computer Science at Nottingham Trent University working on cybersecurity and AI-assisted security testing. More at imranalmunyeem.com.
Top comments (0)