Der Test-Runner unterstützt die folgenden Lifecycle-Hooks. Dies ist nützlich zum Laden von Test-Fixtures, Mocken von Daten und Konfigurieren der Testumgebung.
| Hook | Beschreibung |
|---|---|
beforeAll | Wird einmal vor allen Tests ausgeführt. |
beforeEach | Wird vor jedem Test ausgeführt. |
afterEach | Wird nach jedem Test ausgeführt. |
afterAll | Wird einmal nach allen Tests ausgeführt. |
onTestFinished | Wird ausgeführt, nachdem ein einzelner Test abgeschlossen ist (nach allen afterEach). |
Pro-Test-Setup und -Aufräumung
Führen Sie pro-Test-Setup- und -Aufräumlogik mit beforeEach und afterEach aus.
import { beforeEach, afterEach, test } from "bun:test";
beforeEach(() => {
console.log("Test wird ausgeführt.");
});
afterEach(() => {
console.log("Mit Test fertig.");
});
// Tests...
test("Beispieltest", () => {
// Dieser Test lässt beforeEach davor ausführen
// und afterEach danach
});Pro-Geltungsbereich-Setup und -Aufräumung
Führen Sie pro-Geltungsbereich-Setup- und -Aufräumlogik mit beforeAll und afterAll aus. Der Geltungsbereich wird dadurch bestimmt, wo der Hook definiert ist.
Auf einen Describe-Block beschränkt
Um die Hooks auf einen bestimmten Describe-Block zu beschränken:
import { describe, beforeAll, afterAll, test } from "bun:test";
describe("Testgruppe", () => {
beforeAll(() => {
// Setup für diese Describe-Block
console.log("Testgruppe wird eingerichtet");
});
afterAll(() => {
// Aufräumung für diese Describe-Block
console.log("Testgruppe wird aufgeräumt");
});
test("Test 1", () => {
// Test-Implementierung
});
test("Test 2", () => {
// Test-Implementierung
});
});Auf eine Testdatei beschränkt
Um die Hooks auf eine gesamte Testdatei zu beschränken:
import { describe, beforeAll, afterAll, test } from "bun:test";
beforeAll(() => {
// Setup für gesamte Datei
console.log("Testdatei wird eingerichtet");
});
afterAll(() => {
// Aufräumung für gesamte Datei
console.log("Testdatei wird aufgeräumt");
});
describe("Testgruppe", () => {
test("Test 1", () => {
// Test-Implementierung
});
});onTestFinished
Verwenden Sie onTestFinished, um einen Callback nach Abschluss eines einzelnen Tests auszuführen. Er wird nach allen afterEach-Hooks ausgeführt.
import { test, onTestFinished } from "bun:test";
test("Nach Test aufräumen", () => {
onTestFinished(() => {
// Wird nach allen afterEach-Hooks ausgeführt
console.log("Test abgeschlossen");
});
});Nicht in gleichzeitigen Tests unterstützt; verwenden Sie stattdessen test.serial.
Globales Setup und Aufräumung
Um die Hooks auf einen gesamten mehrdateiligen Testlauf zu beschränken, definieren Sie die Hooks in einer separaten Datei.
import { beforeAll, afterAll } from "bun:test";
beforeAll(() => {
// Globales Setup
console.log("Globales Test-Setup");
// Datenbankverbindungen initialisieren, Server starten usw.
});
afterAll(() => {
// Globale Aufräumung
console.log("Globale Test-Aufräumung");
// Datenbankverbindungen schließen, Server stoppen usw.
});Verwenden Sie dann --preload, um das Setup-Skript vor allen Testdateien auszuführen.
bun test --preload ./setup.tsUm zu vermeiden, dass Sie --preload jedes Mal eingeben müssen, wenn Sie Tests ausführen, kann es zu Ihrer bunfig.toml hinzugefügt werden:
[test]
preload = ["./setup.ts"]Praktische Beispiele
Datenbank-Setup
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
import { createConnection, closeConnection, clearDatabase } from "./db";
let connection;
beforeAll(async () => {
// Mit Test-Datenbank verbinden
connection = await createConnection({
host: "localhost",
database: "test_db",
});
});
afterAll(async () => {
// Datenbankverbindung schließen
await closeConnection(connection);
});
beforeEach(async () => {
// Mit sauberer Datenbank für jeden Test beginnen
await clearDatabase(connection);
});API-Server-Setup
import { beforeAll, afterAll } from "bun:test";
import { startServer, stopServer } from "./server";
let server;
beforeAll(async () => {
// Test-Server starten
server = await startServer({
port: 3001,
env: "test",
});
});
afterAll(async () => {
// Test-Server stoppen
await stopServer(server);
});Mock-Setup
import { beforeEach, afterEach } from "bun:test";
import { mock } from "bun:test";
beforeEach(() => {
// Häufige Mocks einrichten
mock.module("./api-client", () => ({
fetchUser: mock(() => Promise.resolve({ id: 1, name: "Test Benutzer" })),
createUser: mock(() => Promise.resolve({ id: 2 })),
}));
});
afterEach(() => {
// Alle Mocks nach jedem Test zurücksetzen
mock.restore();
});Asynchrone Lifecycle-Hooks
Alle Lifecycle-Hooks unterstützen asynchrone Funktionen:
import { beforeAll, afterAll, test } from "bun:test";
beforeAll(async () => {
// Asynchrones Setup
await new Promise(resolve => setTimeout(resolve, 100));
console.log("Asynchrones Setup abgeschlossen");
});
afterAll(async () => {
// Asynchrone Aufräumung
await new Promise(resolve => setTimeout(resolve, 100));
console.log("Asynchrone Aufräumung abgeschlossen");
});
test("asynchroner Test", async () => {
// Test wartet auf Abschluss von beforeAll
await expect(Promise.resolve("test")).resolves.toBe("test");
});Verschachtelte Hooks
Hooks können verschachtelt werden und werden in der entsprechenden Reihenfolge ausgeführt:
import { describe, beforeAll, beforeEach, afterEach, afterAll, test } from "bun:test";
beforeAll(() => console.log("Datei beforeAll"));
afterAll(() => console.log("Datei afterAll"));
describe("äußeres Describe", () => {
beforeAll(() => console.log("Äußeres beforeAll"));
beforeEach(() => console.log("Äußeres beforeEach"));
afterEach(() => console.log("Äußeres afterEach"));
afterAll(() => console.log("Äußeres afterAll"));
describe("inneres Describe", () => {
beforeAll(() => console.log("Inneres beforeAll"));
beforeEach(() => console.log("Inneres beforeEach"));
afterEach(() => console.log("Inneres afterEach"));
afterAll(() => console.log("Inneres afterAll"));
test("verschachtelter Test", () => {
console.log("Test wird ausgeführt");
});
});
});// Ausgabereihenfolge:
// Datei beforeAll
// Äußeres beforeAll
// Inneres beforeAll
// Äußeres beforeEach
// Inneres beforeEach
// Test wird ausgeführt
// Inneres afterEach
// Äußeres afterEach
// Inneres afterAll
// Äußeres afterAll
// Datei afterAllFehlerbehandlung
Wenn ein Lifecycle-Hook einen Fehler wirft, beeinflusst dies die Testausführung:
import { beforeAll, test } from "bun:test";
beforeAll(() => {
// Wenn dies einen Fehler wirft, werden alle Tests in diesem Geltungsbereich übersprungen
throw new Error("Setup fehlgeschlagen");
});
test("dieser Test wird übersprungen", () => {
// Dies wird nicht ausgeführt, weil beforeAll fehlgeschlagen ist
});Für bessere Fehlerbehandlung:
import { beforeAll, test, expect } from "bun:test";
beforeAll(async () => {
try {
await setupDatabase();
} catch (error) {
console.error("Datenbank-Setup fehlgeschlagen:", error);
throw error; // Erneut werfen, um die Testsuite fehlschlagen zu lassen
}
});Best Practices
Hooks einfach halten
// Gut: Einfaches, fokussiertes Setup
beforeEach(() => {
clearLocalStorage();
resetMocks();
});
// Vermeiden: Komplexe Logik in Hooks
beforeEach(async () => {
// Zu viel komplexe Logik macht Tests schwer zu debuggen
const data = await fetchComplexData();
await processData(data);
await setupMultipleServices(data);
});Angemessenen Geltungsbereich verwenden
// Gut: Setup auf Dateiebene für gemeinsam genutzte Ressourcen
beforeAll(async () => {
await startTestServer();
});
// Gut: Setup auf Testebene für testspezifischen Zustand
beforeEach(() => {
user = createTestUser();
});Ressourcen aufräumen
import { afterAll, afterEach } from "bun:test";
afterEach(() => {
// Nach jedem Test aufräumen
document.body.innerHTML = "";
localStorage.clear();
});
afterAll(async () => {
// Teure Ressourcen aufräumen
await closeDatabase();
await stopServer();
});