supertest With Fastify

When You Need Real Sockets

supertest With Fastify

For integration tests that exercise the real network stack, supertest pairs with app.server after ready().

4 min read Level 2/5 #fastify#testing#supertest
What you'll learn
  • Boot the app with await app.ready()
  • Pass app.server to supertest
  • Assert on real HTTP responses

app.inject() is great for unit and most integration tests. But some plugins, middleware, or proxies behave differently with a real socket — for those, use supertest against app.server after the app is ready().

Setup

npm i -D supertest @types/supertest

A supertest Test

import { test } from 'node:test';
import request from 'supertest';
import { buildApp } from '../src/app.js';

test('GET / over a real socket', async () => {
  const app = buildApp();
  await app.ready();

  await request(app.server)
    .get('/')
    .expect(200)
    .expect('content-type', /json/);

  await app.close();
});

await app.ready() runs all plugin registrations without binding a port. supertest then spins up an ephemeral listener around app.server for the duration of the request.

When to Reach For This

  • Testing TLS, HTTP/2, or socket-level timeouts
  • Verifying proxy headers (X-Forwarded-For) flow correctly
  • Reproducing a bug that only shows up over the wire

For most route logic, prefer app.inject() — supertest is slower and the assertions are chainable but less flexible than asserting on a returned response object.

Testing With Vitest →