Skip to content

O executor de testes oferece suporte aos seguintes hooks de lifecycle. Isso é útil para carregar fixtures de teste, mockar dados e configurar o ambiente de teste.

HookDescrição
beforeAllExecuta uma vez antes de todos os testes.
beforeEachExecuta antes de cada teste.
afterEachExecuta após cada teste.
afterAllExecuta uma vez após todos os testes.
onTestFinishedExecuta após um único teste terminar (após todos afterEach).

Setup e Teardown por Teste

Execute lógica de setup e teardown por teste com beforeEach e afterEach.

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

beforeEach(() => {
  console.log("executando teste.");
});

afterEach(() => {
  console.log("teste concluído.");
});

// testes...
test("exemplo de teste", () => {
  // Este teste terá beforeEach executado antes dele
  // e afterEach executado após ele
});

Setup e Teardown por Escopo

Execute lógica de setup e teardown por escopo com beforeAll e afterAll. O escopo é determinado por onde o hook é definido.

Escopo para um Bloco Describe

Para limitar os hooks a um bloco describe específico:

test.ts
ts
import { describe, beforeAll, afterAll, test } from "bun:test";

describe("grupo de testes", () => {
  beforeAll(() => {
    // setup para este bloco describe
    console.log("Configurando grupo de testes");
  });

  afterAll(() => {
    // teardown para este bloco describe
    console.log("Limpando grupo de testes");
  });

  test("teste 1", () => {
    // implementação do teste
  });

  test("teste 2", () => {
    // implementação do teste
  });
});

Escopo para um Arquivo de Teste

Para limitar os hooks a um arquivo de teste inteiro:

test.ts
ts
import { describe, beforeAll, afterAll, test } from "bun:test";

beforeAll(() => {
  // setup para todo o arquivo
  console.log("Configurando arquivo de teste");
});

afterAll(() => {
  // teardown para todo o arquivo
  console.log("Limpando arquivo de teste");
});

describe("grupo de testes", () => {
  test("teste 1", () => {
    // implementação do teste
  });
});

onTestFinished

Use onTestFinished para executar um callback após um único teste ser concluído. É executado após todos os hooks afterEach.

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

test("limpar após teste", () => {
  onTestFinished(() => {
    // executa após todos hooks afterEach
    console.log("teste finalizado");
  });
});

Não suportado em testes concorrentes; use test.serial em vez disso.

Setup e Teardown Global

Para limitar os hooks a uma execução de teste multi-arquivo inteira, defina os hooks em um arquivo separado.

setup.ts
ts
import { beforeAll, afterAll } from "bun:test";

beforeAll(() => {
  // setup global
  console.log("Setup global de testes");
  // Inicializar conexões de banco de dados, iniciar servidores, etc.
});

afterAll(() => {
  // teardown global
  console.log("Teardown global de testes");
  // Fechar conexões de banco de dados, parar servidores, etc.
});

Então use --preload para executar o script de setup antes de qualquer arquivo de teste.

bash
bun test --preload ./setup.ts

Para evitar digitar --preload toda vez que executar testes, pode ser adicionado ao seu bunfig.toml:

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

Exemplos Práticos

Setup de Banco de Dados

database-setup.ts
ts
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
import { createConnection, closeConnection, clearDatabase } from "./db";

let connection;

beforeAll(async () => {
  // Conectar ao banco de dados de teste
  connection = await createConnection({
    host: "localhost",
    database: "test_db",
  });
});

afterAll(async () => {
  // Fechar conexão com banco de dados
  await closeConnection(connection);
});

beforeEach(async () => {
  // Começar com banco de dados limpo para cada teste
  await clearDatabase(connection);
});

Setup 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 teste
  server = await startServer({
    port: 3001,
    env: "test",
  });
});

afterAll(async () => {
  // Parar servidor de teste
  await stopServer(server);
});

Setup de Mock

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

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

afterEach(() => {
  // Limpar todos mocks após cada teste
  mock.restore();
});

Hooks de Lifecycle Assíncronos

Todos os hooks de lifecycle oferecem suporte a funções assíncronas:

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

beforeAll(async () => {
  // Setup assíncrono
  await new Promise(resolve => setTimeout(resolve, 100));
  console.log("Setup assíncrono concluído");
});

afterAll(async () => {
  // Teardown assíncrono
  await new Promise(resolve => setTimeout(resolve, 100));
  console.log("Teardown assíncrono concluído");
});

test("teste assíncrono", async () => {
  // Teste aguardará beforeAll ser concluído
  await expect(Promise.resolve("test")).resolves.toBe("test");
});

Hooks Aninhados

Hooks podem ser aninhados e serão executados na ordem apropriada:

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("teste aninhado", () => {
      console.log("Teste executando");
    });
  });
});
txt
// Ordem de saída:
// File beforeAll
// Outer beforeAll
// Inner beforeAll
// Outer beforeEach
// Inner beforeEach
// Teste executando
// Inner afterEach
// Outer afterEach
// Inner afterAll
// Outer afterAll
// File afterAll

Tratamento de Erros

Se um hook de lifecycle lançar um erro, afetará a execução do teste:

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

beforeAll(() => {
  // Se isso lançar, todos testes neste escopo serão ignorados
  throw new Error("Setup falhou");
});

test("este teste será ignorado", () => {
  // Não será executado porque beforeAll falhou
});

Para melhor tratamento de erros:

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

beforeAll(async () => {
  try {
    await setupDatabase();
  } catch (error) {
    console.error("Setup do banco de dados falhou:", error);
    throw error; // Re-lançar para falhar a suíte de testes
  }
});

Melhores Práticas

Mantenha Hooks Simples

test.ts
ts
// Bom: Setup simples e focado
beforeEach(() => {
  clearLocalStorage();
  resetMocks();
});

// Evite: Lógica complexa em hooks
beforeEach(async () => {
  // Lógica muito complexa torna testes difíceis de depurar
  const data = await fetchComplexData();
  await processData(data);
  await setupMultipleServices(data);
});

Use Escopo Apropriado

test.ts
ts
// Bom: Setup em nível de arquivo para recursos compartilhados
beforeAll(async () => {
  await startTestServer();
});

// Bom: Setup em nível de teste para estado específico do teste
beforeEach(() => {
  user = createTestUser();
});

Limpar Recursos

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

afterEach(() => {
  // Limpar após cada teste
  document.body.innerHTML = "";
  localStorage.clear();
});

afterAll(async () => {
  // Limpar recursos caros
  await closeDatabase();
  await stopServer();
});

Bun by www.bunjs.com.cn edit