Bun Test Configuration
Set up Bun's built-in test runner with Jest-compatible APIs and significantly faster execution (3-10x faster than Jest).
Quick Reference
For detailed patterns, see:
Jest Migration: jest-migration.md - Complete Jest to Bun migration guide Mocking: mocking.md - Mock functions, spies, module mocking Examples: examples.md - Test patterns for APIs, databases, async code Core Workflow 1. Check Prerequisites
Verify Bun installation
bun --version
Check if project exists
ls -la package.json
- Determine Testing Needs
Ask the user what type of testing they need:
Unit Testing: Test individual functions and modules Integration Testing: Test component interactions API Testing: Test HTTP endpoints Snapshot Testing: Test output consistency 3. Create Test Directory Structure
Create test directories
mkdir -p tests/{unit,integration,fixtures}
Recommended structure:
project/ ├── src/ │ ├── utils.ts │ └── components/ ├── tests/ │ ├── unit/ # Unit tests │ ├── integration/ # Integration tests │ ├── fixtures/ # Test data │ └── setup.ts # Global setup ├── package.json └── bunfig.toml # Test configuration
- Configure Bun Test
Create bunfig.toml in project root:
[ test ]
Preload files before running tests
preload = ["./tests/setup.ts"]
Code coverage
coverage = true coverageDir = "coverage" coverageThreshold = 80
Timeouts (in milliseconds)
timeout = 5000
Bail after first failure
bail = false
- Create Test Setup File
Create tests/setup.ts:
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
// Global test setup beforeAll(() => { console.log("🧪 Starting test suite"); process.env.NODE_ENV = "test"; });
afterAll(() => { console.log("✅ Test suite complete"); });
// Reset mocks before each test beforeEach(() => { // Clear mock state });
afterEach(() => { // Cleanup after each test });
// Global test utilities globalThis.testHelpers = { wait: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)), };
- Write First Test
Create tests/unit/example.test.ts:
import { describe, it, expect, test } from "bun:test";
// Simple test test("addition works", () => { expect(1 + 1).toBe(2); });
// Describe blocks for organization describe("Array utilities", () => { it("should filter even numbers", () => { const numbers = [1, 2, 3, 4, 5, 6]; const evens = numbers.filter(n => n % 2 === 0);
expect(evens).toEqual([2, 4, 6]);
expect(evens).toHaveLength(3);
}); });
// Async tests describe("Async operations", () => { it("should handle promises", async () => { const result = await Promise.resolve(42); expect(result).toBe(42); }); });
For more test examples (API testing, database testing, etc.), see examples.md.
- Add Mocking (If Needed) import { describe, it, expect, mock, spyOn } from "bun:test";
describe("Mock functions", () => { it("should create mock functions", () => { const mockFn = mock((x: number) => x * 2);
const result = mockFn(5);
expect(result).toBe(10);
expect(mockFn).toHaveBeenCalledTimes(1);
expect(mockFn).toHaveBeenCalledWith(5);
});
it("should spy on methods", () => { const obj = { method: (x: number) => x * 2, };
const spy = spyOn(obj, "method");
obj.method(5);
expect(spy).toHaveBeenCalledWith(5);
expect(spy).toHaveReturnedWith(10);
}); });
For advanced mocking patterns, see mocking.md.
- Update package.json
Add test scripts:
{ "scripts": { "test": "bun test", "test:watch": "bun test --watch", "test:coverage": "bun test --coverage", "test:ui": "bun test --coverage --reporter=html" } }
- Run Tests
Run all tests
bun test
Run specific file
bun test tests/unit/utils.test.ts
Watch mode
bun test --watch
With coverage
bun test --coverage
Filter by name
bun test --test-name-pattern="should handle"
Jest Migration
If migrating from Jest, see jest-migration.md for:
Import updates (@jest/globals → bun:test) Mock syntax changes (jest.fn() → mock()) Configuration migration Compatibility notes
Key changes:
// Before (Jest) import { describe, it, expect } from '@jest/globals'; const mockFn = jest.fn();
// After (Bun) import { describe, it, expect, mock } from 'bun:test'; const mockFn = mock();
Common Test Patterns Testing Functions import { test, expect } from "bun:test";
function add(a: number, b: number): number { return a + b; }
test("add function", () => { expect(add(2, 3)).toBe(5); expect(add(-1, 1)).toBe(0); });
Testing Errors test("should throw errors", () => { const throwError = () => { throw new Error("Something went wrong"); };
expect(throwError).toThrow("Something went wrong"); expect(throwError).toThrow(Error); });
test("should reject promises", async () => { const asyncReject = async () => { throw new Error("Async error"); };
await expect(asyncReject()).rejects.toThrow("Async error"); });
Snapshot Testing test("should match snapshot", () => { const data = { id: 1, name: "Test User", email: "test@example.com", };
expect(data).toMatchSnapshot(); });
test("should match inline snapshot", () => { const config = { theme: "dark", language: "en" };
expect(config).toMatchInlineSnapshot({
"theme": "dark",
"language": "en"
});
});
Matchers Reference
Common matchers available:
// Equality expect(value).toBe(expected); // === expect(value).toEqual(expected); // Deep equality
// Truthiness expect(value).toBeTruthy(); expect(value).toBeFalsy(); expect(value).toBeDefined(); expect(value).toBeUndefined();
// Numbers expect(number).toBeGreaterThan(3); expect(number).toBeLessThan(5);
// Strings expect(string).toMatch(/pattern/); expect(string).toContain("substring");
// Arrays expect(array).toContain(item); expect(array).toHaveLength(3);
// Objects expect(object).toHaveProperty("key"); expect(object).toMatchObject({ subset });
// Promises await expect(promise).resolves.toBe(value); await expect(promise).rejects.toThrow();
// Mock functions expect(mockFn).toHaveBeenCalled(); expect(mockFn).toHaveBeenCalledTimes(3); expect(mockFn).toHaveBeenCalledWith(arg1, arg2);
Test Organization Setup and Teardown import { beforeAll, afterAll, beforeEach, afterEach, describe, it } from "bun:test";
describe("User service", () => { let db: Database;
beforeAll(async () => { // Setup before all tests db = await connectToDatabase(); });
afterAll(async () => { // Cleanup after all tests await db.close(); });
beforeEach(async () => { // Reset before each test await db.clear(); });
it("should create user", async () => { const user = await db.users.create({ name: "Test" }); expect(user.id).toBeDefined(); }); });
Coverage Configuration
View coverage report:
Generate coverage
bun test --coverage
View HTML report
bun test --coverage --reporter=html open coverage/index.html
Set coverage thresholds in bunfig.toml:
[ test ] coverage = true coverageThreshold = 80 # Fail if coverage < 80%
Debugging Tests
Run with debugger
bun test --inspect
Verbose output
bun test --verbose
Show all test results
bun test --reporter=tap
Performance
Bun test is significantly faster than Jest:
Jest: ~15 seconds for 100 tests Bun: ~2 seconds for 100 tests
3-10x faster execution!
Completion Checklist ✅ Test directory structure created ✅ bunfig.toml configured ✅ Test setup file created ✅ Example tests written ✅ Package.json scripts updated ✅ Tests run successfully ✅ Coverage configured (if needed) Next Steps
After basic setup:
Write tests: Add tests for critical business logic CI/CD: Configure tests to run in your pipeline Coverage: Set up coverage reporting Pre-commit: Add pre-commit hooks to run tests Documentation: Document testing patterns for the team
For detailed implementations, see the reference files linked above.