Skip to content

bun test ist tief in Buns Laufzeit integriert. Dies ist Teil dessen, was bun test schnell und einfach zu verwenden macht.

Umgebungsvariablen ​

NODE_ENV ​

bun test setzt automatisch $NODE_ENV auf "test", es sei denn, es ist bereits in der Umgebung oder über .env-Dateien gesetzt. Dies ist Standardverhalten für die meisten Test-Runner und hilft, konsistentes Testverhalten sicherzustellen.

test.ts
ts
import { test, expect } from "bun:test";

test("NODE_ENV ist auf test gesetzt", () => {
  expect(process.env.NODE_ENV).toBe("test");
});

Sie können dies überschreiben, indem Sie NODE_ENV explizit setzen:

bash
NODE_ENV=development bun test

TZ (Zeitzone) ​

Standardmäßig verwenden alle bun test-Läufe UTC (Etc/UTC) als Zeitzone, es sei denn, sie wird durch die TZ-Umgebungsvariable überschrieben. Dies stellt konsistentes Datums- und Zeitverhalten über verschiedene Entwicklungsumgebungen hinweg sicher.

test.ts
ts
import { test, expect } from "bun:test";

test("Zeitzone ist standardmäßig UTC", () => {
  const date = new Date();
  expect(date.getTimezoneOffset()).toBe(0);
});

Um mit einer bestimmten Zeitzone zu testen:

bash
TZ=America/New_York bun test

Test-Timeouts ​

Jeder Test hat standardmäßig ein Timeout von 5000ms (5 Sekunden), wenn nicht explizit überschrieben. Tests, die dieses Timeout überschreiten, schlagen fehl.

Globales Timeout ​

Ändern Sie das Timeout global mit dem --timeout-Flag:

bash
bun test --timeout 10000  # 10 Sekunden

Pro-Test-Timeout ​

Legen Sie das Timeout pro Test als dritten Parameter der Testfunktion fest:

test.ts
ts
import { test, expect } from "bun:test";

test("schneller Test", () => {
  expect(1 + 1).toBe(2);
}, 1000); // 1 Sekunde Timeout

test("langsamer Test", async () => {
  await new Promise(resolve => setTimeout(resolve, 8000));
}, 10000); // 10 Sekunden Timeout

Unendliches Timeout ​

Verwenden Sie 0 oder Infinity, um das Timeout zu deaktivieren:

test.ts
ts
test("Test ohne Timeout", async () => {
  // Dieser Test kann unbegrenzt laufen
  await someVeryLongOperation();
}, 0);

Fehlerbehandlung ​

Unbehandelte Fehler ​

bun test verfolgt unbehandelte Promise-Ablehnungen und Fehler, die zwischen Tests auftreten. Wenn solche Fehler auftreten, ist der endgültige Exit-Code ungleich Null (speziell die Anzahl solcher Fehler), selbst wenn alle Tests bestehen.

Dies hilft, Fehler in asynchronem Code zu erkennen, die sonst unbemerkt bleiben könnten:

test.ts
ts
import { test } from "bun:test";

test("Test 1", () => {
  // Dieser Test besteht
  expect(true).toBe(true);
});

// Dieser Fehler tritt außerhalb eines Tests auf
setTimeout(() => {
  throw new Error("Unbehandelter Fehler");
}, 0);

test("Test 2", () => {
  // Dieser Test besteht auch
  expect(true).toBe(true);
});

// Der Testlauf schlägt dennoch mit einem Nicht-Null-Exit-Code fehl
// wegen des unbehandelten Fehlers

Promise-Ablehnungen ​

Unbehandelte Promise-Ablehnungen werden ebenfalls abgefangen:

test.ts
ts
import { test } from "bun:test";

test("bestehender Test", () => {
  expect(1).toBe(1);
});

// Dies führt dazu, dass der Testlauf fehlschlägt
Promise.reject(new Error("Unbehandelte Ablehnung"));

Benutzerdefinierte Fehlerbehandlung ​

Sie können benutzerdefinierte Fehlerhandler in Ihrem Test-Setup einrichten:

test-setup.ts
ts
process.on("uncaughtException", error => {
  console.error("Unbehandelte Ausnahme:", error);
  process.exit(1);
});

process.on("unhandledRejection", (reason, promise) => {
  console.error("Unbehandelte Ablehnung bei:", promise, "Grund:", reason);
  process.exit(1);
});

CLI-Flags-Integration ​

Mehrere Bun-CLI-Flags können mit bun test verwendet werden, um sein Verhalten zu ändern:

Speichernutzung ​

bash
# Reduziert Speichernutzung für die Test-Runner-VM
bun test --smol

Debugging ​

bash
# Hängt den Debugger an den Test-Runner-Prozess an
bun test --inspect
bun test --inspect-brk

Modul-Laden ​

bash
# Führt Skripte vor Testdateien aus (nützlich für globales Setup/Mocks)
bun test --preload ./setup.ts

# Setzt Compile-Zeit-Konstanten
bun test --define "process.env.API_URL='http://localhost:3000'"

# Konfiguriert benutzerdefinierte Loader
bun test --loader .special:special-loader

# Verwendet eine andere tsconfig
bun test --tsconfig-override ./test-tsconfig.json

# Setzt package.json-Bedingungen für Modulauflösung
bun test --conditions development

# Lädt Umgebungsvariablen für Tests
bun test --env-file .env.test

Installationsbezogene Flags ​

bash
# Beeinflusst Netzwerkanfragen oder Auto-Installs während der Testausführung
bun test --prefer-offline
bun test --frozen-lockfile

Watch und Hot Reloading ​

Watch-Mode ​

Bei Verwendung von bun test mit dem --watch-Flag überwacht der Test-Runner Dateiänderungen und führt betroffene Tests erneut aus.

bash
bun test --watch

Der Test-Runner ist intelligent darin, welche Tests erneut ausgeführt werden:

math.test.ts
ts
import { add } from "./math.js";
import { test, expect } from "bun:test";

test("Addition", () => {
  expect(add(2, 3)).toBe(5);
});

Wenn Sie math.js ändern, wird nur math.test.ts erneut ausgeführt, nicht alle Tests.

Hot Reloading ​

Das --hot-Flag bietet ähnliche Funktionalität, ist aber aggressiver beim Versuch, den Zustand zwischen den Läufen zu erhalten:

bash
bun test --hot

Für die meisten Testszenarien ist --watch die empfohlene Option, da sie bessere Isolation zwischen Testläufen bietet.

Globale Variablen ​

Die folgenden Globals sind automatisch in Testdateien verfügbar, ohne zu importieren (obwohl sie bei Bedarf aus bun:test importiert werden können):

test.ts
ts
// Alle diese sind global verfügbar
test("globale Testfunktion", () => {
  expect(true).toBe(true);
});

describe("globales describe", () => {
  beforeAll(() => {
    // globales beforeAll
  });

  it("globale it-Funktion", () => {
    // it ist ein Alias für test
  });
});

// Jest-Kompatibilität
jest.fn();

// Vitest-Kompatibilität
vi.fn();

Sie können sie auch explizit importieren, wenn Sie es vorziehen:

test.ts
ts
import { test, it, describe, expect, beforeAll, beforeEach, afterAll, afterEach, jest, vi } from "bun:test";

Prozess-Integration ​

Exit-Codes ​

bun test verwendet standardmäßige Exit-Codes:

  • 0: Alle Tests bestanden, keine unbehandelten Fehler
  • 1: Testfehler aufgetreten
  • >1: Anzahl unbehandelter Fehler (auch wenn Tests bestanden)

Signal-Behandlung ​

Der Test-Runner behandelt gängige Signale ordnungsgemäß:

bash
# Beendet Testausführung sanft
kill -SIGTERM <test-process-pid>

# Beendet Testausführung sofort
kill -SIGKILL <test-process-pid>

Umgebungserkennung ​

Bun erkennt automatisch bestimmte Umgebungen und passt das Verhalten an:

test.ts
ts
// GitHub Actions-Erkennung
if (process.env.GITHUB_ACTIONS) {
  // Bun gibt automatisch GitHub Actions-Annotationen aus
}

// CI-Erkennung
if (process.env.CI) {
  // Bestimmte Verhaltensweisen können für CI-Umgebungen angepasst werden
}

Performance-Überlegungen ​

Einzelner Prozess ​

Der Test-Runner führt standardmäßig alle Tests in einem einzigen Prozess aus. Dies bietet:

  • Schnellerer Start - Keine Notwendigkeit, mehrere Prozesse zu starten
  • Gemeinsamer Speicher - Effiziente Ressourcennutzung
  • Einfaches Debugging - Alle Tests in einem Prozess

Dies bedeutet jedoch:

  • Tests teilen sich globalen Zustand (verwenden Sie Lifecycle-Hooks zum Aufräumen)
  • Ein Test-Absturz kann andere beeinflussen
  • Keine echte Parallelisierung einzelner Tests

Speicherverwaltung ​

bash
# Speichernutzung überwachen
bun test --smol  # Reduziert Speicherbedarf

# Für große Testsuiten erwägen, Dateien aufzuteilen
bun test src/unit/
bun test src/integration/

Test-Isolation ​

Da Tests im selben Prozess ausgeführt werden, stellen Sie eine ordnungsgemäße Bereinigung sicher:

test.ts
ts
import { afterEach } from "bun:test";

afterEach(() => {
  // Globalen Zustand bereinigen
  global.myGlobalVar = undefined;
  delete process.env.TEST_VAR;

  // Module bei Bedarf zurücksetzen
  jest.resetModules();
});

Umgebungsvariablen für Tests ​

Sie können Umgebungsvariablen für Tests auf verschiedene Arten setzen:

.env-Dateien ​

bash
# .env.test erstellen
DATABASE_URL=postgresql://localhost:5432/test_db
API_URL=http://localhost:3001
test.ts
ts
import { test, expect } from "bun:test";

test("Umgebungsvariablen laden", () => {
  expect(process.env.DATABASE_URL).toContain("test_db");
  expect(process.env.API_URL).toBe("http://localhost:3001");
});

CLI-Flags ​

bash
# Umgebungsvariablen inline setzen
DATABASE_URL=test bun test

# Oder mit --env-file
bun test --env-file .env.test

In Test-Setup ​

test-setup.ts
ts
process.env.NODE_ENV = "test";
process.env.LOG_LEVEL = "error";
process.env.SUPPRESS_WARNINGS = "true";

Module Resolution in Tests ​

Bun verwendet dieselbe Modulauflösung für Tests wie für normalen Code:

test.ts
ts
// Relative Importe
import { myFunction } from "./my-module";

// Paket-Importe
import express from "express";

// Absolute Importe (mit tsconfig paths)
import { utils } from "@/utils";

TypeScript-Unterstützung ​

Bun transpiliert TypeScript automatisch während des Testens:

math.test.ts
ts
import { test, expect } from "bun:test";

function add(a: number, b: number): number {
  return a + b;
}

test("Addition", () => {
  expect(add(2, 3)).toBe(5);
});

JSX-Unterstützung ​

JSX wird in Tests ohne zusätzliche Konfiguration unterstützt:

component.test.tsx
tsx
import { test, expect } from "bun:test";

function Button({ children }: { children: React.ReactNode }) {
  return <button>{children}</button>;
}

test("Button rendert", () => {
  const button = <Button>Klick mich</Button>;
  expect(button).toBeDefined();
});

Best Practices ​

Test-Umgebung isolieren ​

test-setup.ts
ts
import { beforeEach, afterEach } from "bun:test";

beforeEach(() => {
  // Sauberen Zustand für jeden Test sicherstellen
  jest.clearAllMocks();
  process.env = { ...process.env, NODE_ENV: "test" };
});

afterEach(() => {
  // Nach jedem Test bereinigen
  jest.restoreAllMocks();
});

Asynchrone Tests richtig handhaben ​

async.test.ts
ts
import { test, expect } from "bun:test";

test("asynchrone Operation", async () => {
  const result = await asyncFunction();
  expect(result).toBe("expected");
});

test("Promise-basierte Assertion", async () => {
  await expect(asyncFunction()).resolves.toBe("expected");
  await expect(failingFunction()).rejects.toThrow("error");
});

Ressourcen verwalten ​

resource.test.ts
ts
import { test, expect, beforeEach, afterEach } from "bun:test";

let server;

beforeEach(async () => {
  server = await startTestServer();
});

afterEach(async () => {
  await server.stop();
});

test("Server antwortet", async () => {
  const response = await fetch(server.url);
  expect(response.status).toBe(200);
});

Bun von www.bunjs.com.cn bearbeitet