NODEJS Contents

Testing Express APIs

Supertest is a practical way to test HTTP behavior in-memory: it validates routing, middleware order, and error formats without real network overhead.

On this page

Why HTTP Testing Needs a Tool

Testing HTTP endpoints by manually calling handlers misses middleware behavior, route matching, headers, and serialization. Supertest runs requests against your app without binding an actual port, keeping tests fast and deterministic.

Test the Contract, Not the Implementation

API tests should assert status codes, response shape, headers, and error codes. Avoid asserting exact formatting or internal logs. Treat the HTTP interface as the contract.

Example: Express + Supertest

import test from 'node:test';
import assert from 'node:assert/strict';
import request from 'supertest';
import { createApp } from '../src/app';

test('GET /health returns ok', async () => {
  const app = createApp();
  const res = await request(app).get('/health').expect(200);
  assert.deepEqual(res.body, { ok: true });
});

Example: Validate Error Format

test('POST /users validates input', async () => {
  const app = createApp();

  const res = await request(app)
    .post('/users')
    .set('Content-Type', 'application/json')
    .send({ email: 123 })
    .expect(400);

  assert.equal(res.body.error.code, 'VALIDATION_ERROR');
});

Production Tips

  • Build the app in a factory function so tests can create isolated instances
  • Use a dedicated test DB or mock repositories where appropriate
  • Keep HTTP tests focused on contract-critical routes