Mental Model
Global fixtures are designed for managing external resources that exist outside the JavaScript memory space of your tests.
Key Characteristics:
- Execution: Guaranteed to run exactly once.
- Consistency: Works in parallel, watch, and serial modes.
- Isolation: They do not share a context with tests, suites, or other hooks. You cannot access properties attached to
this inside a global fixture from within a describe or it block. - Context Sharing:
mochaGlobalSetup and mochaGlobalTeardown do share a context (this), allowing you to pass data between setup and teardown.
When to use
Use global fixtures for spinning up external resources that tests access via I/O, such as:
- Web servers
- Sockets
- Databases (to start/stop the process)
When NOT to use
Do not use global fixtures to manage in-memory values (like file handles or database connection objects) that you need to access directly in your tests. Because tests cannot access the fixture's context, they won't be able to see these values.
Correct Pattern: Use a global fixture to start the external resource (e.g., the database process), and use root hook plugins or standard hooks to create the actual connection/client used by the tests.
// Example of the recommended pattern:
// 1. Global fixture starts the server
// 2. Test hooks connect to the server
// fixtures.mjs
let server;
export const mochaGlobalSetup = async () => {
server = await startSomeServer({ port: process.env.TEST_PORT });
};
export const mochaGlobalTeardown = async () => {
await server.stop();
};
// test.spec.mjs
import { connect } from "my-server-connector-thingy";
describe("my API", function () {
let connection;
before(async function () {
connection = await connect({ port: process.env.TEST_PORT });
});
it("should be a nice API", function () {
// assertions here
});
after(async function () {
return connection.close();
});
});