Skip to main content

node-test

Basics

First test and running it

// math.test.js
const { test } = require('node:test');
const assert = require('node:assert');

test('adds 1 + 2 to equal 3', () => {
assert.strictEqual(1 + 2, 3);
});

Run the file directly using the --test flag:

node --test math.test.js

Or, if you name your files *.test.js or place them in a test/ directory, you can simply run:

node --test

NOTE

Node will automatically discover and run files matching *.test.js, *-test.js, or test.js.

Test suites

You can create test suites with the describe() function from the node:test library

const { test, describe, it } = require('node:test');
const assert = require('node:assert');

// Using basic test()
test('a simple test', () => {
assert.ok(true);
});

// Using describe and it
describe('Math operations', () => {
it('should add correctly', () => {
assert.strictEqual(1 + 1, 2);
});

it('should subtract correctly', () => {
assert.strictEqual(2 - 1, 1);
});
});

Test filtering

const { test } = require('node:test');
const assert = require('node:assert');

// Skip a test
test('skip this test', { skip: true }, () => {
// This will not run
});

// Skip with a reason
test('skip this test', { skip: 'Feature not implemented yet' }, () => {});

// Focus: Run ONLY this test (using the 'only' option)
test('run only this test', { only: true }, () => {
assert.strictEqual(1, 1);
});

// To run 'only' tests, you must pass the --test-only flag in the CLI:
// node --test --test-only

Assertions in depth

Assertions come from the node:assert library:

const assert = require('node:assert');

// 1. Equality (strict comparison, use this 95% of the time)
assert.strictEqual(1, 1); // Passes
// assert.strictEqual(1, '1'); // Fails

// 2. Deep Equality (for objects and arrays)
assert.deepStrictEqual([1, 2], [1, 2]); // Passes
assert.deepStrictEqual({ a: 1 }, { a: 1 }); // Passes

// 3. Truthy / Falsy
assert.ok(true); // Passes if value is truthy
assert.ok(1);

// 4. Expected to throw
assert.throws(() => {
throw new Error('Something went wrong');
}, /Something went wrong/); // Optional regex or error object matching

// 5. Expected to reject (for Promises)
assert.rejects(
async () => { throw new Error('Async error'); },
/Async error/
);

Hooks

const { describe, test, before, after, beforeEach, afterEach } = require('node:test');
const assert = require('node:assert');

describe('Database Suite', () => {
before(() => {
console.log('Runs once before all tests in this suite');
});

after(() => {
console.log('Runs once after all tests in this suite');
});

beforeEach(() => {
console.log('Runs before every test');
});

afterEach(() => {
console.log('Runs after every test');
});

test('test 1', () => {
assert.ok(true);
});

test('test 2', () => {
assert.ok(true);
});
});

Async tests

const { test } = require('node:test');
const assert = require('node:assert');

// Async/await
test('async test', async () => {
const result = await Promise.resolve(42);
assert.strictEqual(result, 42);
});

// Callbacks (using Node's util.promisify or standard async patterns)
// Note: Node's test runner does NOT support "done" callbacks like Mocha.
// If you have callback-based code, wrap it in a Promise.
test('callback-based test wrapped in promise', async () => {
await new Promise((resolve, reject) => {
setTimeout(() => {
assert.ok(true);
resolve();
}, 100);
});
});

Mocking

Basics

const { test, mock } = require('node:test');
const assert = require('node:assert');

test('mocking a function', () => {
// Create a mock function
const myMock = mock.fn((x) => x * 2);

myMock(5);
myMock(10);

// Assert it was called correctly
assert.strictEqual(myMock.mock.calls.length, 2);
assert.strictEqual(myMock.mock.calls[0].arguments[0], 5);
assert.strictEqual(myMock.mock.results[0].value, 10);

// ALWAYS restore mocks after the test to prevent side effects
mock.restoreAll();
});

test('mocking an object method', () => {
const calculator = {
add: (a, b) => a + b,
};

// Mock the method
mock.method(calculator, 'add', () => 100);

assert.strictEqual(calculator.add(1, 2), 100);
assert.strictEqual(calculator.add.mock.calls.length, 1);

mock.restoreAll();
});