테스트 러너는 다음 라이프사이클 훅을 지원합니다. 이는 테스트 픽스처 로드, 데이터 목킹 및 테스트 환경 구성에 유용합니다.
| 훅 | 설명 |
|---|---|
beforeAll | 모든 테스트 전에 한 번 실행됩니다. |
beforeEach | 각 테스트 전에 실행됩니다. |
afterEach | 각 테스트 후에 실행됩니다. |
afterAll | 모든 테스트 후에 한 번 실행됩니다. |
onTestFinished | 단일 테스트가 끝난 후 실행됩니다 (모든 afterEach 후). |
테스트당 설정 및 정리
beforeEach 와 afterEach 를 사용하여 테스트당 설정 및 정리 로직을 수행하세요.
ts
import { beforeEach, afterEach, test } from "bun:test";
beforeEach(() => {
console.log("테스트 실행 중.");
});
afterEach(() => {
console.log("테스트 완료.");
});
// 테스트...
test("예시 테스트", () => {
// 이 테스트는 전에 beforeEach 가 실행되고
// 후에 afterEach 가 실행됩니다
});스코프당 설정 및 정리
beforeAll 과 afterAll 을 사용하여 스코프당 설정 및 정리 로직을 수행하세요. 스코프는 훅이 정의된 위치에 따라 결정됩니다.
Describe 블록에 스코프 지정
특정 describe 블록에 훅을 스코프하려면.
ts
import { describe, beforeAll, afterAll, test } from "bun:test";
describe("테스트 그룹", () => {
beforeAll(() => {
// 이 describe 블록에 대한 설정
console.log("테스트 그룹 설정");
});
afterAll(() => {
// 이 describe 블록에 대한 정리
console.log("테스트 그룹 정리");
});
test("테스트 1", () => {
// 테스트 구현
});
test("테스트 2", () => {
// 테스트 구현
});
});테스트 파일에 스코프 지정
훅을 전체 테스트 파일에 스코프하려면.
ts
import { describe, beforeAll, afterAll, test } from "bun:test";
beforeAll(() => {
// 전체 파일에 대한 설정
console.log("테스트 파일 설정");
});
afterAll(() => {
// 전체 파일에 대한 정리
console.log("테스트 파일 정리");
});
describe("테스트 그룹", () => {
test("테스트 1", () => {
// 테스트 구현
});
});onTestFinished
onTestFinished 을 사용하여 단일 테스트가 완료된 후 콜백을 실행하세요. 이는 모든 afterEach 훅 후에 실행됩니다.
ts
import { test, onTestFinished } from "bun:test";
test("테스트 후 정리", () => {
onTestFinished(() => {
// 모든 afterEach 훅 후에 실행
console.log("테스트 완료");
});
});동시 테스트에서는 지원되지 않습니다. 대신 test.serial 을 사용하세요.
전역 설정 및 정리
훅을 전체 멀티 파일 테스트 실행에 스코프하려면 별도 파일에서 훅을 정의하세요.
ts
import { beforeAll, afterAll } from "bun:test";
beforeAll(() => {
// 전역 설정
console.log("전역 테스트 설정");
// 데이터베이스 연결 초기화, 서버 시작 등
});
afterAll(() => {
// 전역 정리
console.log("전역 테스트 정리");
// 데이터베이스 연결 종료, 서버 중지 등
});그런 다음 --preload 를 사용하여 테스트 파일 전에 설정 스크립트를 실행하세요.
bash
bun test --preload ./setup.ts테스트를 실행할 때마다 --preload 를 입력하지 않으려면 bunfig.toml 에 추가할 수 있습니다.
toml
[test]
preload = ["./setup.ts"]실제 예시
데이터베이스 설정
ts
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
import { createConnection, closeConnection, clearDatabase } from "./db";
let connection;
beforeAll(async () => {
// 테스트 데이터베이스에 연결
connection = await createConnection({
host: "localhost",
database: "test_db",
});
});
afterAll(async () => {
// 데이터베이스 연결 종료
await closeConnection(connection);
});
beforeEach(async () => {
// 각 테스트마다 깨끗한 데이터베이스로 시작
await clearDatabase(connection);
});API 서버 설정
ts
import { beforeAll, afterAll } from "bun:test";
import { startServer, stopServer } from "./server";
let server;
beforeAll(async () => {
// 테스트 서버 시작
server = await startServer({
port: 3001,
env: "test",
});
});
afterAll(async () => {
// 테스트 서버 중지
await stopServer(server);
});목 설정
ts
import { beforeEach, afterEach } from "bun:test";
import { mock } from "bun:test";
beforeEach(() => {
// 일반적인 목 설정
mock.module("./api-client", () => ({
fetchUser: mock(() => Promise.resolve({ id: 1, name: "Test User" })),
createUser: mock(() => Promise.resolve({ id: 2 })),
}));
});
afterEach(() => {
// 각 테스트 후 모든 목 초기화
mock.restore();
});비동기 라이프사이클 훅
모든 라이프사이클 훅은 async 함수를 지원합니다.
ts
import { beforeAll, afterAll, test } from "bun:test";
beforeAll(async () => {
// 비동기 설정
await new Promise(resolve => setTimeout(resolve, 100));
console.log("비동기 설정 완료");
});
afterAll(async () => {
// 비동기 정리
await new Promise(resolve => setTimeout(resolve, 100));
console.log("비동기 정리 완료");
});
test("비동기 테스트", async () => {
// beforeAll 이 완료될 때까지 테스트가 대기합니다
await expect(Promise.resolve("test")).resolves.toBe("test");
});중첩 훅
훅은 중첩될 수 있으며 적절한 순서로 실행됩니다.
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("중첩 테스트", () => {
console.log("테스트 실행");
});
});
});txt
// 출력 순서:
// File beforeAll
// Outer beforeAll
// Inner beforeAll
// Outer beforeEach
// Inner beforeEach
// Test running
// Inner afterEach
// Outer afterEach
// Inner afterAll
// Outer afterAll
// File afterAll오류 처리
라이프사이클 훅이 오류를 발생시키면 테스트 실행에 영향을 미칩니다.
ts
import { beforeAll, test } from "bun:test";
beforeAll(() => {
// 이 오류가 발생하면 이 스코프의 모든 테스트가 건너뜁니다
throw new Error("설정 실패");
});
test("이 테스트는 건너뜁니다", () => {
// beforeAll 이 실패했으므로 실행되지 않습니다
});더 나은 오류 처리를 위해.
ts
import { beforeAll, test, expect } from "bun:test";
beforeAll(async () => {
try {
await setupDatabase();
} catch (error) {
console.error("데이터베이스 설정 실패:", error);
throw error; // 테스트 스위트 실패를 위해 다시 던지기
}
});모범 사례
훅을 간단하게 유지
ts
// 좋음: 단순하고 집중된 설정
beforeEach(() => {
clearLocalStorage();
resetMocks();
});
// 피하기: 훅의 복잡한 로직은 테스트 디버깅을 어렵게 함
beforeEach(async () => {
// 너무 많은 복잡한 로직
const data = await fetchComplexData();
await processData(data);
await setupMultipleServices(data);
});적절한 스코프 사용
ts
// 좋음: 공유 리소스에 대한 파일 수준 설정
beforeAll(async () => {
await startTestServer();
});
// 좋음: 테스트별 상태에 대한 테스트 수준 설정
beforeEach(() => {
user = createTestUser();
});리소스 정리
ts
import { afterAll, afterEach } from "bun:test";
afterEach(() => {
// 각 테스트 후 정리
document.body.innerHTML = "";
localStorage.clear();
});
afterAll(async () => {
// 비싼 리소스 정리
await closeDatabase();
await stopServer();
});