The built-in node:test module includes mocking tools for replacing functions and methods during tests. Mocks help isolate one unit of code from external services, slow operations, clocks, or behavior that is difficult to reproduce.
Use Node.js 22 or later. Put the imports and the four tests below in one file named mocking.test.cjs. The .cjs extension keeps these examples in CommonJS mode.
Import the Test API
Example:
const test = require('node:test');
const assert = require('node:assert/strict');
Mock a Function
Example:
test('formats a mocked result', t => {
const loadName = t.mock.fn(() => 'Asha');
assert.equal(loadName(), 'Asha');
assert.equal(loadName.mock.callCount(), 1);
});
t.mock.fn() creates a mock function and records how it was called.
Inspect Calls
Example:
test('tracks arguments', t => {
const send = t.mock.fn();
send('email', 42);
const call = send.mock.calls[0];
assert.equal(call.arguments[0], 'email');
assert.equal(call.arguments[1], 42);
});
Call records are useful when the return value is not enough to prove correct behavior.
Mock an Object Method
Example:
test('replaces a method', t => {
const service = {
status() {
return 'online';
}
};
t.mock.method(service, 'status', () => 'offline');
assert.equal(service.status(), 'offline');
});
Method mocking is useful when the code under test receives an object dependency and calls one of its methods.
Restore Test State
Mocks created through the test context are designed to be cleaned up with the test lifecycle. Explicit restore APIs are also available when you need to return behavior earlier.
Mock Timers
The Node.js test runner can control selected timer behavior so a test does not have to wait for real time to pass.
Example:
test('timer-controlled code', t => {
t.mock.timers.enable({ apis: ['setTimeout'] });
let done = false;
setTimeout(() => {
done = true;
}, 1000);
t.mock.timers.tick(1000);
assert.equal(done, true);
});
Timer mocking makes timeout, retry, and delayed-work tests faster and more deterministic.
| Tool | Use |
|---|---|
| mock.fn() | Create a tracked function |
| mock.method() | Replace an object method |
| mock.calls | Inspect recorded calls |
| mock.timers | Control supported timer APIs |
Mock only the dependency boundary you need. Over-mocking can make a test pass while the real components no longer work together.
Run the Tests
Example:
node --test mocking.test.cjs
All four tests should pass. Test-runner formatting and duration fields vary by Node.js version; a timer-mocking experimental warning may also appear in older releases.
Conclusion
Node.js test runner mocks can replace functions, methods, and timers while recording how the mocked code was used. This makes unit tests faster and more focused without requiring an additional mocking framework for common cases.