Testing with the Node.js Built-in Test Runner (node:test)

A
Author
17 Sep, 2026 1 min read 694 views

Node.js ships a full test runner. For many backends and libraries it replaces Jest or Mocha entirely, with zero dependencies.

Writing tests

// test/cart.test.js
import { describe, it, beforeEach } from 'node:test';
import assert from 'node:assert/strict';
import { Cart } from '../src/cart.js';

describe('Cart', () => {
  let cart;
  beforeEach(() => { cart = new Cart(); });

  it('starts empty', () => {
    assert.equal(cart.total(), 0);
  });

  it('sums item prices', () => {
    cart.add({ price: 100, qty: 2 });
    cart.add({ price: 50, qty: 1 });
    assert.equal(cart.total(), 250);
  });

  it('rejects negative quantities', () => {
    assert.throws(() => cart.add({ price: 10, qty: -1 }), /quantity/);
  });
});

Running

node --test                       # finds *.test.js, *-test.js, test/**/*.js and similar
node --test --watch               # re-run on changes
node --test --test-name-pattern="sums"
node --test --experimental-test-coverage

Async code

it('fetches a user', async () => {
  const user = await getUser(1);
  assert.deepEqual(user, { id: 1, name: 'Asha' });
});

it('rejects for unknown ids', async () => {
  await assert.rejects(getUser(999), { message: 'Not found' });
});

Mocking

import { it, mock } from 'node:test';

it('sends a welcome email', async (t) => {
  const send = t.mock.fn(async () => ({ id: 'msg_1' }));
  await registerUser({ email: 'a@b.com' }, { mailer: { send } });

  assert.equal(send.mock.callCount(), 1);
  assert.equal(send.mock.calls[0].arguments[0].to, 'a@b.com');
});

it('expires sessions after an hour', (t) => {
  t.mock.timers.enable({ apis: ['Date', 'setTimeout'] });
  const session = createSession();
  t.mock.timers.tick(60 * 60 * 1000 + 1);
  assert.equal(session.isExpired(), true);
});

Mocks created with t.mock are restored automatically after each test.

When to still reach for Vitest or Jest

  • Frontend component tests that need a DOM environment and bundler transforms.
  • Snapshot-heavy suites or a team already invested in their ecosystems.
Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.