Lesson 20 / 32

Testing Routes

Test Fastify routes quickly with fastify.inject and Node's built-in test runner, with no real server.

In-process testing

Fastify can inject requests directly without starting a real server—ideal for unit and integration tests.

Testing with inject

Use fastify.inject() to send requests and verify responses.

import test from 'node:test';
import assert from 'node:assert';
import build from './app.js';

test('GET /health returns 200', async () => {
  const fastify = await build();
  
  const response = await fastify.inject({
    method: 'GET',
    url: '/health',
  });
  
  assert.equal(response.statusCode, 200);
  assert.deepEqual(JSON.parse(response.body), { status: 'ok' });
  
  await fastify.close();
});

Testing with inject, no network

inject simulates a request in memory using light-my-request.

  • No port is opened.
  • res.statusCode and res.json() read the answer.
const test = require('node:test');
const assert = require('node:assert');
const Fastify = require('fastify');

test('GET /ping', async () => {
  const app = Fastify();
  app.get('/ping', async () => ({ pong: true }));
  const res = await app.inject({ method: 'GET', url: '/ping' });
  assert.strictEqual(res.statusCode, 200);
  assert.deepStrictEqual(res.json(), { pong: true });
});

Quick check

Quick check: Why prefer `app.inject()` over starting a server and calling fetch in unit tests?

  • It is faster and needs no free port
  • It skips all hooks
  • It works only for POST
Answer

It is faster and needs no free port — inject runs the full lifecycle in-process, so hooks and validation still apply.