Engineering4 min read

API Testing

Test APIs thoroughly - REST endpoint testing with Supertest, contract testing with Pact, authentication scenarios, and error case coverage.

API TestingRESTSupertestPactContract Testing

skill: API Testing category: Engineering tags: [API Testing, REST, Supertest, Pact, Contract Testing] readingTime: 4

API tests are the sweet spot of the testing pyramid - faster than E2E, higher-level than unit tests. A comprehensive API test suite verifies that the HTTP interface works correctly without requiring a browser. Test every HTTP status code your API returns, not just 200 OK.

Workflow

  1. Test REST endpoints with SupertestSupertest sends real HTTP requests to your Express/Fastify/Hono server without starting an actual network listener. Tests run in-process, fast, with access to the test database.
  2. Test all response codesAPIs return many status codes - 400 for bad input, 401 for auth, 403 for authorization, 404 for not found, 409 for conflict, 422 for validation. Untested paths are unverified behavior.
  3. Validate OpenAPI schemasSchema validation catches API drift - when the code diverges from the documented contract. Automated schema validation prevents silent breaking changes.
  4. Write contract tests with PactPact tests verify that provider APIs fulfill the contracts that consumers depend on - catching breaking changes before they reach production in microservices architectures.
  5. Test authentication and authorizationAuth bugs are security vulnerabilities, not just test failures. Systematically test auth matrix - every role × every endpoint.

Output Format

API testing: Supertest in-process HTTP, test all status codes (201/400/401/403/409/422), AJV schema validation vs OpenAPI, Pact consumer→provider contract, and auth matrix for every role×endpoint.

request(app).get("/api/orders").set("Authorization", bearer).query({ page:0 }).expect(200)
.expect(401) without token; .expect(403) for wrong user; .expect(422) for invalid input
ajv.compile(openApiSchema)(response.body) → schema drift detection
PactV3: consumer defines expectation → provider verifies
Auth matrix: [unauthenticated, user, admin] × [public, authenticated, adminOnly] endpoints

Examples

Input

Output

Edge Cases & Gotchas

  • Test database isolation - Tests mutating the same database table in parallel fail nondeterministically. Use transactions that rollback after each test, or create uniquely named test resources (email with timestamp).
  • Rate limiting in tests - Rate limiting middleware blocks rapid test requests. Disable rate limiting in test environment, or reset the rate limit counter in beforeEach for tests that deliberately probe rate limit behavior.
  • Large file upload testing - Supertest supports file uploads: request(app).post("/upload").attach("file", Buffer.from("content"), { filename: "test.pdf", contentType: "application/pdf" }).
  • Idempotency key testing - Payment and order APIs with idempotency keys need tests for: first call (creates), second call with same key (returns same response without duplicating), different key (creates new).

When to Break These Rules

  • Use Postman/Newman for API testing when the team is non-technical (QA with limited coding experience) - Postman's GUI is more accessible than code-based Supertest.
  • Use k6 or Gatling for load testing API endpoints - Supertest is single-threaded and can't simulate concurrent user load.

Reference Files

  • https://github.com/ladjs/supertest
  • https://docs.pact.io/

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.