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