Skip to content

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.

HookDescripción
beforeAllSe ejecuta una vez antes de todas las pruebas.
beforeEachSe ejecuta antes de cada prueba.
afterEachSe ejecuta después de cada prueba.
afterAllSe ejecuta una vez después de todas las pruebas.
onTestFinishedSe 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.

test.ts
ts
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:

test.ts
ts
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:

test.ts
ts
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.

test.ts
ts
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.

setup.ts
ts
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.

bash
bun test --preload ./setup.ts

Para evitar escribir --preload cada vez que ejecutas pruebas, puede agregarse a tu bunfig.toml:

bunfig.toml
toml
[test]
preload = ["./setup.ts"]

Ejemplos prácticos

Configuración de base de datos

database-setup.ts
ts
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

server-setup.ts
ts
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

mock-setup.ts
ts
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:

test.ts
ts
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:

test.ts
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("prueba anidada", () => {
      console.log("Ejecutando prueba");
    });
  });
});
txt
// Orden de salida:
// File beforeAll
// Outer beforeAll
// Inner beforeAll
// Outer beforeEach
// Inner beforeEach
// Ejecutando prueba
// Inner afterEach
// Outer afterEach
// Inner afterAll
// Outer afterAll
// File afterAll

Manejo de errores

Si un hook de ciclo de vida lanza un error, afectará la ejecución de pruebas:

test.ts
ts
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:

test.ts
ts
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

test.ts
ts
// 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

test.ts
ts
// 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

test.ts
ts
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();
});

Bun por www.bunjs.com.cn editar