API Testing Guide

What to Test in Every API Endpoint

CategoryTest Cases
Happy pathValid input โ†’ expected response body, correct status code
ValidationMissing required fields, wrong types, boundary values
AuthenticationNo token โ†’ 401, expired token โ†’ 401, invalid token โ†’ 401
AuthorizationCorrect user but wrong role โ†’ 403, access other user's data โ†’ 403
Not foundNon-existent ID โ†’ 404
IdempotencyRepeated POST with same key โ†’ same result, no duplicate
ConcurrencyRace conditions on shared resources
Response schemaAll expected fields present, correct types

Integration Tests with Supertest (Node.js)

import request from 'supertest'; import app from '../app'; import { db } from '../db'; describe('POST /api/users', () => { afterEach(() => db.users.deleteMany({})); // clean up it('creates a user and returns 201', async () => { const res = await request(app) .post('/api/users') .send({ name: 'Alice', email: '[email protected]' }) .expect(201) .expect('Content-Type', /json/); expect(res.body).toMatchObject({ id: expect.any(String), name: 'Alice', email: '[email protected]', createdAt: expect.any(String) }); }); it('returns 400 when email is missing', async () => { const res = await request(app) .post('/api/users') .send({ name: 'Alice' }) .expect(400); expect(res.body.error).toContain('email'); }); it('returns 409 when email already exists', async () => { await db.users.create({ name: 'Alice', email: '[email protected]' }); await request(app) .post('/api/users') .send({ name: 'Bob', email: '[email protected]' }) .expect(409); }); });

Newman (CLI) & Postman Automation

# Run Postman collection from CLI newman run collection.json \ --environment staging.env.json \ --reporters cli,json \ --reporter-json-export results.json # In CI/CD (GitHub Actions) # - name: Run API tests # run: | # newman run tests/api-collection.json \ # --env-var "BASE_URL=${{ env.API_URL }}" \ # --env-var "API_KEY=${{ secrets.API_KEY }}" # Postman test script example (in Tests tab) pm.test("Status code is 200", () => { pm.response.to.have.status(200); }); pm.test("Response schema is valid", () => { const schema = { type: "object", required: ["id", "name", "email"], properties: { id: { type: "string" }, name: { type: "string" }, email: { type: "string", format: "email" } } }; pm.response.to.have.jsonSchema(schema); }); // Save token for subsequent requests const token = pm.response.json().token; pm.environment.set("AUTH_TOKEN", token);