Setup & Teardown
Use beforeEach, afterEach, beforeAll, and afterAll for test lifecycle hooks.
beforeEach and afterEach
beforeEach runs before every test in scope; afterEach runs after every test regardless of pass/fail. Use for resetting mocks, recreating fixtures, and cleaning DOM.
Keep afterEach cleanup defensive—tests should not depend on previous test cleanup succeeding.
let db: TestDatabase;
beforeEach(async () => {
db = await createTestDatabase();
});
afterEach(async () => {
await db.destroy();
});beforeAll and afterAll
beforeAll runs once before all tests in describe block; afterAll once after all complete. Expensive one-time setup—starting test server, connecting database—belongs here.
If beforeAll fails, tests in block may not run. Share read-only fixtures via beforeAll when mutation per test is not required.
- Nested describe blocks inherit and scope hooks
- Hooks can be async—return promise or use async function
- afterAll still runs if tests fail unless process crashes
let server: Server;
beforeAll(async () => {
server = await startServer();
});
afterAll(async () => {
await server.close();
});Scoped Setup with describe
Group related tests in describe with shared hooks and variables. Inner describe blocks add narrower scope for specialized setup without affecting sibling groups.
Avoid deep nesting beyond three levels—flat structure with helper functions often reads better.
describe("AuthService", () => {
describe("login", () => {
beforeEach(() => seedUser());
test("returns token", () => { /* ... */ });
});
});Database and Integration Setup
Run migrations before integration test suite. Use transactions rolled back after each test for fast isolation, or truncate tables in afterEach.
Testcontainers spin up real databases in Docker—afterAll must stop containers to avoid CI resource leaks.
beforeEach(async () => {
await db.query("BEGIN");
});
afterEach(async () => {
await db.query("ROLLBACK");
});Global Setup
globalSetup and globalTeardown in Jest config run once per test run across all files—for starting shared services or generating coverage baseline.
setupFilesAfterEnv runs before each test file—import jest-dom matchers and configure mock defaults there.
// jest.config.ts
export default {
setupFilesAfterEnv: ["<rootDir>/test/setup.ts"],
globalSetup: "<rootDir>/test/globalSetup.ts",
};