Testing with the Node.js Built-in Test Runner (node:test)
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.