| name | bun-test |
| description | Configure Bun's built-in test runner with Jest-compatible APIs. Use when setting up testing infrastructure, writing unit/integration/snapshot tests, migrating from Jest, or configuring test coverage. 3-10x faster than Jest. |
| compatibility | Requires Bun 1.0+ |
| allowed-tools | ["Bash","Write","Read"] |
| metadata | {"author":"dale","category":"bun-runtime","tags":["bun","testing","jest","unit-tests","tdd"]} |
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
bun --version
ls -la package.json
2. 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
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
4. Configure Bun Test
Create bunfig.toml in project root:
[test]
preload = ["./tests/setup.ts"]
coverage = true
coverageDir = "coverage"
coverageThreshold = 80
timeout = 5000
bail = false
5. Create Test Setup File
Create tests/setup.ts:
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
beforeAll(() => {
console.log("🧪 Starting test suite");
process.env.NODE_ENV = "test";
});
afterAll(() => {
console.log("✅ Test suite complete");
});
beforeEach(() => {
});
afterEach(() => {
});
globalThis.testHelpers = {
wait: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)),
};
6. Write First Test
Create tests/unit/example.test.ts:
import { describe, it, expect, test } from "bun:test";
test("addition works", () => {
expect(1 + 1).toBe(2);
});
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);
});
});
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.
7. 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.
8. 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"
}
}
9. Run Tests
bun test
bun test tests/unit/utils.test.ts
bun test --watch
bun test --coverage
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:
import { describe, it, expect } from '@jest/globals';
const mockFn = jest.fn();
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:
expect(value).toBe(expected);
expect(value).toEqual(expected);
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeDefined();
expect(value).toBeUndefined();
expect(number).toBeGreaterThan(3);
expect(number).toBeLessThan(5);
expect(string).toMatch(/pattern/);
expect(string).toContain("substring");
expect(array).toContain(item);
expect(array).toHaveLength(3);
expect(object).toHaveProperty("key");
expect(object).toMatchObject({ subset });
await expect(promise).resolves.toBe(value);
await expect(promise).rejects.toThrow();
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 () => {
db = await connectToDatabase();
});
afterAll(async () => {
await db.close();
});
beforeEach(async () => {
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:
bun test --coverage
bun test --coverage --reporter=html
open coverage/index.html
Set coverage thresholds in bunfig.toml:
[test]
coverage = true
coverageThreshold = 80
Debugging Tests
bun test --inspect
bun test --verbose
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.