Use Mocha rootHooks to Run Setup Once Across Test Files
Mocha 8.2 and later run root hooks once for an entire test run, so shared setup does not repeat in every spec file.
19 May 2026, 16:26 UTC

The problem: repeating setup in every spec file
Imagine a Node project with dozens of Mocha spec files. Each file opens the same test database, loads the same environment variables, or starts the same test container. That means copying beforeAll and afterAll boilerplate into every file. Add a new spec and forget the setup, and the suite fails or leaves connections open.
The useful takeaway: Mocha 8.2 and later support root hooks. Declared once in configuration, they run before and after the entire Mocha process, so shared setup lives in one place instead of every spec file.
Where root hooks fit in a Mocha run
A spec file is a test file Mocha loads and executes. Root hooks live outside any describe block. beforeAll and afterAll run exactly once for the full run. beforeEach and afterEach run before and after every test in every loaded file. Because root hooks execute outside describe, they cannot use the this context that describe-level hooks can access.
Worked example: shared test database
Use a JavaScript config file because root hook values are functions, which JSON cannot represent. Create or edit .mocharc.js in the project root:
// .mocharc.js
import { createTestDatabase } from './test/helpers/database.js';
export default {
rootHooks: {
beforeAll: async function () {
process.env.NODE_ENV = 'test';
global.testDb = await createTestDatabase();
},
afterAll: async function () {
await global.testDb.close();
}
}
};
A spec file can then assume the connection already exists:
// test/user.spec.js
import { expect } from 'chai';
import { getUsers } from '../src/users.js';
describe('users', () => {
it('returns rows from the shared test database', async () => {
const users = await getUsers(global.testDb);
expect(users).to.be.an('array');
});
});
Run the suite from the project root:
npx mocha
No elevated permissions are required. The root beforeAll runs before the first spec, and root afterAll runs after the last spec finishes.
Check the version and verify behavior
First confirm Mocha is new enough:
npx mocha --version
Expect 8.2.0 or higher. Older releases ignore rootHooks.
To verify the hooks run once, temporarily add console.log statements to beforeAll and afterAll, then run:
npx mocha
Confirm the startup message prints exactly once before any suite output and the teardown message prints exactly once after all suite output. Remove the temporary logs before committing.
Trade-offs and limitations
- A root hook that throws aborts the entire run, not just one spec file.
- An async root hook that throws without being awaited can hang the process or appear as a run-level error rather than a test failure.
- Because root hooks apply to every spec Mocha loads, broad setup can slow unrelated tests and make failures harder to isolate.
- Root hooks cannot use per-test or per-suite this context.
When to use them and how to revert
Use root hooks for repository-wide concerns such as loading test environment variables, starting test containers, or opening a shared test database. Keep file-specific setup inside describe blocks so individual specs remain independent.
To revert, delete the rootHooks block from .mocharc.js and run the suite again. Each spec should then manage its own setup or fail visibly if it depends on the removed shared state.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.