Building an API and testing it thoroughly are equally important. An API that works in one scenario but fails silently in another is worse than useless โ it erodes trust and creates hard-to-debug problems in the React frontend. Postman is the tool that closes this gap. In this lesson you will build a complete Postman collection for the MERN Blog API โ covering all endpoints, all edge cases, success paths and failure paths, with environment variables for effortless switching between development and production, and automated test scripts that verify your API’s correctness in one click.
Why Thorough API Testing Matters Before Building the Frontend
| Benefit | Detail |
|---|---|
| Isolate bugs | If the API works in Postman but fails in React, the bug is in the React code |
| Test all edge cases | Missing fields, invalid IDs, expired tokens, wrong roles โ easy in Postman, hard to trigger from a UI |
| Verify status codes | Postman shows exact HTTP status โ React often swallows these in error handling |
| Living documentation | A saved, organised collection is the best API documentation for your team |
| Regression testing | Run the full collection with one click to confirm nothing broke after changes |
{{authToken}} in the Authorization header of every protected request. Every time you log in, all protected requests are updated instantly with the new token โ no manual copying and pasting.{{variableName}}) โ not the environment file that contains the actual values. Store the environment file separately and never commit it to Git.Setting Up the Postman Environment
Create Environment: "MERN Blog โ Development"
Variables:
baseUrl โ http://localhost:5000/api (initial value)
authToken โ (empty โ set automatically after login)
userId โ (empty โ set after registration)
postId โ (empty โ set after creating a post)
Create Environment: "MERN Blog โ Production"
Variables:
baseUrl โ https://your-api.render.com/api
authToken โ (empty)
userId โ (empty)
postId โ (empty)
Switching environments:
Top-right dropdown in Postman โ select "MERN Blog โ Development"
All {{baseUrl}} references resolve to http://localhost:5000/api
One click to switch to Production โ all URLs update automatically
Collection Structure
MERN Blog API/
โโโ Auth/
โ โโโ Register โ POST {{baseUrl}}/auth/register
โ โโโ Login โ POST {{baseUrl}}/auth/login โ auto-saves token
โ โโโ Get Me โ GET {{baseUrl}}/auth/me
โ โโโ Logout โ POST {{baseUrl}}/auth/logout
โโโ Posts/
โ โโโ Get All Posts โ GET {{baseUrl}}/posts
โ โโโ Get All (filtered) โ GET {{baseUrl}}/posts?tag=mern&page=1&limit=5
โ โโโ Get Post by ID โ GET {{baseUrl}}/posts/{{postId}}
โ โโโ Create Post โ POST {{baseUrl}}/posts
โ โโโ Update Post โ PATCH {{baseUrl}}/posts/{{postId}}
โ โโโ Delete Post โ DELETE {{baseUrl}}/posts/{{postId}}
โโโ Posts โ Error Cases/
โ โโโ Get Post โ Invalid ID format
โ โโโ Get Post โ Non-existent ID
โ โโโ Create Post โ Missing title
โ โโโ Create Post โ No auth token
โ โโโ Delete Post โ Not owner
โ โโโ Update Post โ Expired token
โโโ Users/
โโโ Get User Profile โ GET {{baseUrl}}/users/{{userId}}
โโโ Update Profile โ PATCH {{baseUrl}}/users/{{userId}}
Auto-Setting the Auth Token After Login
// Postman โ Login request โ Scripts tab โ Post-response tab
// Paste this script โ it runs automatically after every login response
const response = pm.response.json();
if (response.success && response.token) {
pm.environment.set('authToken', response.token);
pm.environment.set('userId', response.data._id);
console.log('Token saved to environment variable authToken');
} else {
console.warn('Login failed โ token not saved:', response.message);
}
// Now in every protected request, set the Authorization header to:
// Bearer {{authToken}}
// Postman replaces {{authToken}} with the saved token automatically
Auto-Setting postId After Creating a Post
// Postman โ Create Post request โ Scripts โ Post-response
const response = pm.response.json();
if (response.success && response.data._id) {
pm.environment.set('postId', response.data._id);
console.log('Post ID saved:', response.data._id);
}
Writing Test Scripts
// Postman โ Any request โ Scripts โ Post-response tab
// Tests run automatically after every request when using Collection Runner
// โโ Test: successful POST /auth/login โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pm.test('Status is 200', () => {
pm.response.to.have.status(200);
});
pm.test('Response has success: true', () => {
const json = pm.response.json();
pm.expect(json.success).to.be.true;
});
pm.test('Response contains token', () => {
const json = pm.response.json();
pm.expect(json.token).to.be.a('string');
pm.expect(json.token.length).to.be.above(10);
});
pm.test('Response time under 500ms', () => {
pm.expect(pm.response.responseTime).to.be.below(500);
});
// โโ Test: GET /api/posts โ paginated list โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pm.test('Status is 200', () => pm.response.to.have.status(200));
pm.test('Response shape is correct', () => {
const json = pm.response.json();
pm.expect(json).to.have.property('success', true);
pm.expect(json).to.have.property('count');
pm.expect(json).to.have.property('total');
pm.expect(json).to.have.property('page');
pm.expect(json).to.have.property('pages');
pm.expect(json.data).to.be.an('array');
});
// โโ Test: GET /api/posts/invalid-id โ 400 bad request โโโโโโโโโโโโโโโโโโโโโ
pm.test('Status is 400 for invalid ID', () => {
pm.response.to.have.status(400);
});
pm.test('Error response shape', () => {
const json = pm.response.json();
pm.expect(json.success).to.be.false;
pm.expect(json.message).to.be.a('string');
});
// โโ Test: DELETE without auth โ 401 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
pm.test('Status is 401 without token', () => {
pm.response.to.have.status(401);
});
Running the Full Test Suite
Method 1 โ Postman Collection Runner (GUI):
1. Click the "โถ" button next to your collection name
2. Select environment: "MERN Blog โ Development"
3. Click "Run MERN Blog API"
4. Postman runs all requests in order
5. Green = test passed, Red = test failed
6. Summary shows pass/fail count and any failed assertions
Method 2 โ Newman (CLI โ for CI/CD):
npm install -g newman
# Export collection from Postman: Collection โ ... โ Export โ v2.1
# Export environment: Environments โ ... โ Export
newman run "MERN Blog API.postman_collection.json" \
--environment "MERN Blog โ Development.postman_environment.json" \
--reporters cli,json \
--reporter-json-export results.json
# Exit code 0 = all tests passed, 1 = failures
# Use in GitHub Actions CI to block merges if API tests fail
Common Mistakes
Mistake 1 โ Only testing the happy path
โ Wrong โ testing only successful requests:
POST /api/posts with valid body โ 201 โ (only test)
// Missing: what about missing title? invalid ID? no auth? wrong role?
โ Correct โ for every endpoint test at least: success case, missing auth, validation failure, and resource not found.
Mistake 2 โ Hardcoding tokens and IDs in requests
โ Wrong โ copying a JWT token directly into the Authorization header value:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
// Token expires โ every request fails โ manually copy new token โ tedious
โ Correct โ use environment variables and the post-login script to auto-update the token.
Mistake 3 โ Not testing with multiple user roles
โ Wrong โ only testing as an admin user who can do everything:
All tests pass as admin... but regular users can also delete any post!
โ The authorisation bug is never caught because tests only run as admin
โ Correct โ create separate environments or variables for admin, regular user, and no-auth states. Test ownership checks by logging in as user A and trying to delete user B’s post.
Quick Reference
| Postman Feature | How to Use |
|---|---|
| Environment variable | {{variableName}} in URL, headers, or body |
| Set variable in script | pm.environment.set('key', value) |
| Get variable in script | pm.environment.get('key') |
| Assert status | pm.response.to.have.status(200) |
| Assert body property | pm.expect(json.success).to.be.true |
| Assert array | pm.expect(json.data).to.be.an('array') |
| Run collection | Collection โ โถ Run โ Select env โ Run |
| CLI runner | newman run collection.json --environment env.json |