El ejecutor de pruebas admite los siguientes hooks de ciclo de vida. Esto es útil para cargar fixtures de prueba, simular datos y configurar el entorno de pruebas.
| Hook | Descripción |
|---|---|
beforeAll | Se ejecuta una vez antes de todas las pruebas. |
beforeEach | Se ejecuta antes de cada prueba. |
afterEach | Se ejecuta después de cada prueba. |
afterAll | Se ejecuta una vez después de todas las pruebas. |
onTestFinished | Se ejecuta después de que una sola prueba termina (después de todos los afterEach). |
Configuración y limpieza por prueba
Realiza lógica de configuración y limpieza por prueba con beforeEach y afterEach.
import { beforeEach, afterEach, test } from "bun:test";
beforeEach(() => {
console.log("ejecutando prueba.");
});
afterEach(() => {
console.log("prueba terminada.");
});
// pruebas...
test("ejemplo de prueba", () => {
// Esta prueba tendrá beforeEach ejecutándose antes
// y afterEach ejecutándose después
});Configuración y limpieza por ámbito
Realiza lógica de configuración y limpieza por ámbito con beforeAll y afterAll. El ámbito está determinado por dónde se define el hook.
Ámbito de un bloque Describe
Para limitar los hooks a un bloque describe particular:
import { describe, beforeAll, afterAll, test } from "bun:test";
describe("grupo de pruebas", () => {
beforeAll(() => {
// configuración para este bloque describe
console.log("Configurando grupo de pruebas");
});
afterAll(() => {
// limpieza para este bloque describe
console.log("Limpiando grupo de pruebas");
});
test("prueba 1", () => {
// implementación de prueba
});
test("prueba 2", () => {
// implementación de prueba
});
});Ámbito de un archivo de prueba
Para limitar los hooks a un archivo de prueba completo:
import { describe, beforeAll, afterAll, test } from "bun:test";
beforeAll(() => {
// configuración para todo el archivo
console.log("Configurando archivo de prueba");
});
afterAll(() => {
// limpieza para todo el archivo
console.log("Limpiando archivo de prueba");
});
describe("grupo de pruebas", () => {
test("prueba 1", () => {
// implementación de prueba
});
});onTestFinished
Usa onTestFinished para ejecutar una devolución de llamada después de que una sola prueba se complete. Se ejecuta después de todos los hooks afterEach.
import { test, onTestFinished } from "bun:test";
test("limpiar después de la prueba", () => {
onTestFinished(() => {
// se ejecuta después de todos los hooks afterEach
console.log("prueba terminada");
});
});No soportado en pruebas concurrentes; usa test.serial en su lugar.
Configuración y limpieza global
Para limitar los hooks a una ejecución de pruebas multiarchivo completa, define los hooks en un archivo separado.
import { beforeAll, afterAll } from "bun:test";
beforeAll(() => {
// configuración global
console.log("Configuración global de pruebas");
// Inicializar conexiones de base de datos, iniciar servidores, etc.
});
afterAll(() => {
// limpieza global
console.log("Limpieza global de pruebas");
// Cerrar conexiones de base de datos, detener servidores, etc.
});Luego usa --preload para ejecutar el script de configuración antes de cualquier archivo de prueba.
bun test --preload ./setup.tsPara evitar escribir --preload cada vez que ejecutas pruebas, puede agregarse a tu bunfig.toml:
[test]
preload = ["./setup.ts"]Ejemplos prácticos
Configuración de base de datos
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
import { createConnection, closeConnection, clearDatabase } from "./db";
let connection;
beforeAll(async () => {
// Conectar a la base de datos de pruebas
connection = await createConnection({
host: "localhost",
database: "test_db",
});
});
afterAll(async () => {
// Cerrar conexión de base de datos
await closeConnection(connection);
});
beforeEach(async () => {
// Comenzar con base de datos limpia para cada prueba
await clearDatabase(connection);
});Configuración de servidor API
import { beforeAll, afterAll } from "bun:test";
import { startServer, stopServer } from "./server";
let server;
beforeAll(async () => {
// Iniciar servidor de pruebas
server = await startServer({
port: 3001,
env: "test",
});
});
afterAll(async () => {
// Detener servidor de pruebas
await stopServer(server);
});Configuración de mocks
import { beforeEach, afterEach } from "bun:test";
import { mock } from "bun:test";
beforeEach(() => {
// Configurar mocks comunes
mock.module("./api-client", () => ({
fetchUser: mock(() => Promise.resolve({ id: 1, name: "Usuario de prueba" })),
createUser: mock(() => Promise.resolve({ id: 2 })),
}));
});
afterEach(() => {
// Limpiar todos los mocks después de cada prueba
mock.restore();
});Hooks de ciclo de vida async
Todos los hooks de ciclo de vida admiten funciones async:
import { beforeAll, afterAll, test } from "bun:test";
beforeAll(async () => {
// Configuración async
await new Promise(resolve => setTimeout(resolve, 100));
console.log("Configuración async completada");
});
afterAll(async () => {
// Limpieza async
await new Promise(resolve => setTimeout(resolve, 100));
console.log("Limpieza async completada");
});
test("prueba async", async () => {
// La prueba esperará a que beforeAll se complete
await expect(Promise.resolve("test")).resolves.toBe("test");
});Hooks anidados
Los hooks pueden anidarse y se ejecutarán en el orden apropiado:
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("prueba anidada", () => {
console.log("Ejecutando prueba");
});
});
});// Orden de salida:
// File beforeAll
// Outer beforeAll
// Inner beforeAll
// Outer beforeEach
// Inner beforeEach
// Ejecutando prueba
// Inner afterEach
// Outer afterEach
// Inner afterAll
// Outer afterAll
// File afterAllManejo de errores
Si un hook de ciclo de vida lanza un error, afectará la ejecución de pruebas:
import { beforeAll, test } from "bun:test";
beforeAll(() => {
// Si esto lanza, todas las pruebas en este ámbito se omitirán
throw new Error("Configuración fallida");
});
test("esta prueba se omitirá", () => {
// Esto no se ejecutará porque beforeAll falló
});Para mejor manejo de errores:
import { beforeAll, test, expect } from "bun:test";
beforeAll(async () => {
try {
await setupDatabase();
} catch (error) {
console.error("Configuración de base de datos fallida:", error);
throw error; // Volver a lanzar para fallar la suite de pruebas
}
});Mejores prácticas
Mantener los hooks simples
// Bueno: Configuración simple y enfocada
beforeEach(() => {
clearLocalStorage();
resetMocks();
});
// Evitar: Lógica compleja en hooks
beforeEach(async () => {
// Demasiada lógica compleja hace que las pruebas sean difíciles de depurar
const data = await fetchComplexData();
await processData(data);
await setupMultipleServices(data);
});Usar el ámbito apropiado
// Bueno: Configuración a nivel de archivo para recursos compartidos
beforeAll(async () => {
await startTestServer();
});
// Bueno: Configuración a nivel de prueba para estado específico de prueba
beforeEach(() => {
user = createTestUser();
});Limpiar recursos
import { afterAll, afterEach } from "bun:test";
afterEach(() => {
// Limpiar después de cada prueba
document.body.innerHTML = "";
localStorage.clear();
});
afterAll(async () => {
// Limpiar recursos costosos
await closeDatabase();
await stopServer();
});