Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Testing: inject and node:test

A test is code that calls your API and checks the reply. Fastify can run a request right in memory with app.inject(): no port is taken, no network is needed, and the test is fast. Tests are run by the node:test module built into Node.js, so there is nothing to install.

The run script

Add a script to package.json:

{
  "scripts": {
    "test": "node --test"
  }
}

node --test finds and runs files with names like *.test.js.

The first test

This is where separating app.js and server.js pays off: the test creates the application with buildApp without calling listen. Create test/posts.test.js:

// test/posts.test.js
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { buildApp } from '../src/app.js';
 
process.env.DB_FILE = ':memory:';
process.env.JWT_SECRET = 'test-secret-1234567890';
process.env.ADMIN_NAME = 'anna';
process.env.ADMIN_PASSWORD = 'test-password';
 
test('GET /posts returns an empty list', async (t) => {
  const app = buildApp();
  t.after(() => app.close());
 
  const response = await app.inject({ method: 'GET', url: '/posts' });
 
  assert.equal(response.statusCode, 200);
  assert.deepEqual(response.json(), []);
});

DB_FILE=':memory:' creates an empty in-memory database for the test, so real posts are not affected. t.after() closes the application after the test, and response.json() parses the reply body.

Run the tests:

npm test

The terminal shows the test name marked as passed and the summary pass 1.

A request with a body

You can pass a method, address, headers and a body to inject — Fastify turns an object into JSON:

// test/posts.test.js
test('POST /posts without a token returns 401', async (t) => {
  const app = buildApp();
  t.after(() => app.close());
 
  const response = await app.inject({
    method: 'POST',
    url: '/posts',
    payload: { title: 'Test', body: 'Text' },
  });
 
  assert.equal(response.statusCode, 401);
});

The test confirms that the protection from the authentication lesson works.

What the reply has

PropertyWhat it holds
response.statusCodeStatus code
response.headersReply headers
response.bodyThe body as a string
response.json()The body parsed from JSON

Common mistake

If you do not close the application after a test, the open database and other plugin resources can keep the process alive, and npm test hangs after printing the results. The onClose hooks do not run either. Add t.after(() => app.close()) to every test that creates an application.

Thanks for reading!

Donate to the site — we work hard for you.