温馨提示:本站仅提供公开网络链接索引服务,不存储、不篡改任何第三方内容,所有内容版权归原作者所有
AI智能索引来源:http://www.bun.com/docs/test/lifecycle
点击访问原文链接

Lifecycle hooks - Bun

Lifecycle hooks - BunDocumentation Index

Fetch the complete documentation index at: /docs/llms.txt

Use this file to discover all available pages before exploring further.

Skip to main contentBun home pageSearch...⌘KInstall BunSearch...NavigationTest FeaturesLifecycle hooksRuntimePackage ManagerBundlerTest RunnerGuidesReferenceBlogFeedback:first-child]:!hidden peer-[.is-custom]:[&>:first-child]:sm:!hidden peer-[.is-custom]:[&>:first-child]:md:!hidden peer-[.is-custom]:[&>:first-child]:lg:!hidden peer-[.is-custom]:[&>:first-child]:xl:!hidden">Getting StartedTest runnerWriting testsTest configurationTest ExecutionRuntime behaviorFinding testsTest FeaturesLifecycle hooksMocksSnapshotsDates and timesSpecialized TestingDOM testingReportingCode coverageTest ReportersOn this pagePer-Test Setup and TeardownPer-Scope Setup and TeardownScoped to a Describe BlockScoped to a Test FileonTestFinishedGlobal Setup and TeardownPractical ExamplesDatabase SetupAPI Server SetupMock SetupAsync Lifecycle HooksNested HooksError HandlingBest PracticesKeep Hooks SimpleUse Appropriate ScopeClean Up ResourcesTest FeaturesLifecycle hooksCopy pagespan]:line-clamp-1 overflow-hidden group flex items-center py-0.5 gap-1 text-sm text-gray-950/50 dark:text-white/50 group-hover:text-gray-950/70 dark:group-hover:text-white/70 rounded-none rounded-r-xl border px-3 border-gray-200 aspect-square dark:border-white/[0.07] bg-background-light dark:bg-background-dark hover:bg-gray-600/5 dark:hover:bg-gray-200/5" aria-label="More actions" type="button" id="radix-_R_n4ctdbsnlht5lebsnpfdb_" aria-haspopup="menu" aria-expanded="false" data-state="closed">*]:[overflow-wrap:anywhere]">

Learn how to use beforeAll, beforeEach, afterEach, and afterAll lifecycle hooks in Bun tests

Copy pagespan]:line-clamp-1 overflow-hidden group flex items-center py-0.5 gap-1 text-sm text-gray-950/50 dark:text-white/50 group-hover:text-gray-950/70 dark:group-hover:text-white/70 rounded-none rounded-r-xl border px-3 border-gray-200 aspect-square dark:border-white/[0.07] bg-background-light dark:bg-background-dark hover:bg-gray-600/5 dark:hover:bg-gray-200/5" aria-label="More actions" type="button" id="radix-_R_1cctdbsnlht5lebsnpfdb_" aria-haspopup="menu" aria-expanded="false" data-state="closed">The test runner supports the following lifecycle hooks. This is useful for loading test fixtures, mocking data, and configuring the test environment. HookDescriptionbeforeAllRuns once before all tests.beforeEachRuns before each test.afterEachRuns after each test.afterAllRuns once after all tests.onTestFinishedRuns after a single test finishes (after all afterEach). ​Per-Test Setup and Teardown Perform per-test setup and teardown logic with beforeEach and afterEach. test.ts
import { beforeEach, afterEach, test } from "bun:test";

beforeEach(() => {
console.log("running test.");
});

afterEach(() => {
console.log("done with test.");
});

// tests...
test("example test", () => {
// This test will have beforeEach run before it
// and afterEach run after it
});
​Per-Scope Setup and Teardown Perform per-scope setup and teardown logic with beforeAll and afterAll. The scope is determined by where the hook is defined. ​Scoped to a Describe Block To scope the hooks to a particular describe block: test.ts
import { describe, beforeAll, afterAll, test } from "bun:test";

describe("test group", () => {
beforeAll(() => {
// setup for this describe block
console.log("Setting up test group");
});

afterAll(() => {
// teardown for this describe block
console.log("Tearing down test group");
});

test("test 1", () => {
// test implementation
});

test("test 2", () => {
// test implementation
});
});
​Scoped to a Test File To scope the hooks to an entire test file: test.ts
import { describe, beforeAll, afterAll, test } from "bun:test";

beforeAll(() => {
// setup for entire file
console.log("Setting up test file");
});

afterAll(() => {
// teardown for entire file
console.log("Tearing down test file");
});

describe("test group", () => {
test("test 1", () => {
// test implementation
});
});
​onTestFinished Use onTestFinished to run a callback after a single test completes. It runs after all afterEach hooks. test.ts
import { test, onTestFinished } from "bun:test";

test("cleanup after test", () => {
onTestFinished(() => {
// runs after all afterEach hooks
console.log("test finished");
});
});
Not supported in concurrent tests; use test.serial instead. ​Global Setup and Teardown To scope the hooks to an entire multi-file test run, define the hooks in a separate file. setup.ts
import { beforeAll, afterAll } from "bun:test";

beforeAll(() => {
// global setup
console.log("Global test setup");
// Initialize database connections, start servers, etc.
});

afterAll(() => {
// global teardown
console.log("Global test teardown");
// Close database connections, stop servers, etc.
});
Then use --preload to run the setup script before any test files. terminal
bun test --preload ./setup.ts
To avoid typing --preload every time you run tests, it can be added to your bunfig.toml: bunfig.toml
[test]
preload = ["./setup.ts"]
​Practical Examples ​Database Setup database-setup.ts
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
import { createConnection, closeConnection, clearDatabase } from "./db";

let connection;

beforeAll(async () => {
// Connect to test database
connection = await createConnection({
host: "localhost",
database: "test_db",
});
});

afterAll(async () => {
// Close database connection
await closeConnection(connection);
});

beforeEach(async () => {
// Start with clean database for each test
await clearDatabase(connection);
});
​API Server Setup server-setup.ts
import { beforeAll, afterAll } from "bun:test";
import { startServer, stopServer } from "./server";

let server;

beforeAll(async () => {
// Start test server
server = await startServer({
port: 3001,
env: "test",
});
});

afterAll(async () => {
// Stop test server
await stopServer(server);
});
​Mock Setup mock-setup.ts
import { beforeEach, afterEach } from "bun:test";
import { mock } from "bun:test";

beforeEach(() => {
// Set up common mocks
mock.module("./api-client", () => ({
fetchUser: mock(() => Promise.resolve({ id: 1, name: "Test User" })),
createUser: mock(() => Promise.resolve({ id: 2 })),
}));
});

afterEach(() => {
// Clear all mocks after each test
mock.restore();
});
​Async Lifecycle Hooks All lifecycle hooks support async functions: test.ts
import { beforeAll, afterAll, test } from "bun:test";

beforeAll(async () => {
// Async setup
await new Promise(resolve => setTimeout(resolve, 100));
console.log("Async setup complete");
});

afterAll(async () => {
// Async teardown
await new Promise(resolve => setTimeout(resolve, 100));
console.log("Async teardown complete");
});

test("async test", async () => {
// Test will wait for beforeAll to complete
await expect(Promise.resolve("test")).resolves.toBe("test");
});
​Nested Hooks Hooks can be nested and will run in the appropriate order: test.ts
import { describe, beforeAll, beforeEach, afterEach, afterAll, test } from "bun:test";

beforeAll(() => console.log("File beforeAll"));
afterAll(() => console.log("File afterAll"));

describe("outer describe", () => {
beforeAll(() => console.log("Outer beforeAll"));
beforeEach(() => console.log("Outer beforeEach"));
afterEach(() => console.log("Outer afterEach"));
afterAll(() => console.log("Outer afterAll"));

describe("inner describe", () => {
beforeAll(() => console.log("Inner beforeAll"));
beforeEach(() => console.log("Inner beforeEach"));
afterEach(() => console.log("Inner afterEach"));
afterAll(() => console.log("Inner afterAll"));

test("nested test", () => {
console.log("Test running");
});
});
});
// Output order:
// File beforeAll
// Outer beforeAll
// Inner beforeAll
// Outer beforeEach
// Inner beforeEach
// Test running
// Inner afterEach
// Outer afterEach
// Inner afterAll
// Outer afterAll
// File afterAll
​Error Handling If a lifecycle hook throws an error, it will affect test execution: test.ts
import { beforeAll, test } from "bun:test";

beforeAll(() => {
// If this throws, all tests in this scope will be skipped
throw new Error("Setup failed");
});

test("this test will be skipped", () => {
// This won't run because beforeAll failed
});
For better error handling: test.ts
import { beforeAll, test, expect } from "bun:test";

beforeAll(async () => {
try {
await setupDatabase();
} catch (error) {
console.error("Database setup failed:", error);
throw error; // Re-throw to fail the test suite
}
});
​Best Practices ​Keep Hooks Simple test.ts
// Good: Simple, focused setup
beforeEach(() => {
clearLocalStorage();
resetMocks();
});

// Avoid: Complex logic in hooks
beforeEach(async () => {
// Too much complex logic makes tests hard to debug
const data = await fetchComplexData();
await processData(data);
await setupMultipleServices(data);
});
​Use Appropriate Scope test.ts
// Good: File-level setup for shared resources
beforeAll(async () => {
await startTestServer();
});

// Good: Test-level setup for test-specific state
beforeEach(() => {
user = createTestUser();
});
​Clean Up Resources test.ts
import { afterAll, afterEach } from "bun:test";

afterEach(() => {
// Clean up after each test
document.body.innerHTML = "";
localStorage.clear();
});

afterAll(async () => {
// Clean up expensive resources
await closeDatabase();
await stopServer();
});

Was this page helpful?

YesNoSuggest editsRaise issueFinding testsPreviousMocksNext⌘IxgithubdiscordyoutubePowered byThis documentation is built and hosted on Mintlify, a developer documentation platform

Lifecycle hooks - Bun,AI智能索引,全网链接索引,智能导航,网页索引

    Learn how to use beforeAll, beforeEach, afterEach, and afterAll lifecycle hooks in Bun tests