bun-testing
Testing guidelines for Bun/TypeScript projects using bun:test framework. Use when writing tests, creating test files, debugging test failures, setting up mocks, or reviewing test code. Triggers on *.test.ts files, test-related questions, mocking patterns, and coverage discussions.
When & Why to Use This Skill
This Claude skill provides comprehensive testing guidelines and utilities for Bun and TypeScript projects using the native bun:test framework. It streamlines the development of unit, integration, and endpoint tests by offering standardized patterns for module mocking, database lifecycle management, and environment configuration, ensuring robust code quality and efficient debugging.
Use Cases
- Writing unit tests for TypeScript business logic using bun:test and ModuleMocker to effectively isolate dependencies.
- Setting up integration tests that require a real database environment using Docker-based test containers and automated database reset scripts.
- Testing Hono-based API endpoints using the createTestApp utility and specialized request helpers for POST and GET operations.
- Improving test coverage and reliability by implementing standardized mocking strategies for external APIs and shared services.
- Debugging complex test failures by following the arrange-act-assert pattern and utilizing descriptive naming conventions for better traceability.
| name | bun-testing |
|---|---|
| description | Testing guidelines for Bun/TypeScript projects using bun:test framework. Use when writing tests, creating test files, debugging test failures, setting up mocks, or reviewing test code. Triggers on *.test.ts files, test-related questions, mocking patterns, and coverage discussions. |
Bun Testing Skill
Quick Reference
- Framework: bun:test
- File pattern:
*.test.tsinside__tests__directories - Module mocking: Use
ModuleMockerfrom@/__tests__(see patterns) - Coverage target: 60–80% (focus on important logic, not 100%)
- Config:
.env.testfor test environment variables
Test Utilities (src/tests/)
Before writing custom test helpers, check existing utilities:
createTestApp(basePath, route, middleware[])- Creates test Hono app with error handler, logger, and optional middlewareModuleMocker(import.meta.url)- Module mocking utility (see mocking patterns)post(app, url, body, headers)- POST request helperget(app, url, headers)- GET request helperdoRequest(app, url, method, body, headers)- Generic request helper
Example:
import { createTestApp, post } from '@/__tests__'
const app = createTestApp('/api/v1/auth', signupRoute, [captchaMiddleware()])
const response = await post(app, '/api/v1/auth/signup', {
email: 'test@example.com',
password: 'SecurePass123!'
})
Test Types
- Unit tests: Mock all dependencies (repositories, services, APIs)
- Integration tests: Use real database, mock external APIs only
- Endpoint tests: Use
createTestApp()with mocked services
Test Priorities
- Correct scenario(s)
- Error handling
- Boundary inputs
- Failure scenarios
Database Testing
For integration tests requiring real database:
- Use
bun run db:up:test(starts test DB on port 5433) - Use
bun run db:down:test(stops test DB) - Use
bun run test:with-db(starts DB + runs tests) - Test DB uses separate Docker container (
smela-db-test) and.env.testconfig - Reset DB state between test suites if needed using
bun run db:reset:test
Environment Setup
- Use
.env.testfor test-specific variables - Bun handles env loading natively — no manual dotenv needed
- Minimize mocking
@/env— only mock for special/invalid configs
Mocking Strategy
- Mock only business logic dependencies (repositories, external APIs)
- Use global mocks for shared services (CAPTCHA, email) — don't redefine per test
- No real database or network calls — all I/O must be mocked
- Don't mock encapsulated dependencies — mock the public API/wrapper only
Type Safety
- Minimize
any— prefer proper TypeScript types - Use type inference when possible
- Use
Partial<T>for mock objects - Exception: Use
anyonly for complex mocks where full typing adds unnecessary complexity
Test Structure
Use arrange → act → assert pattern with descriptive test names:
describe('UserService', () => {
it('should return user when found by email', async () => {
// Arrange
const mockUser = { id: 1, email: 'test@example.com' }
mockUserRepo.findByEmail.mockResolvedValue(mockUser)
// Act
const result = await userService.findByEmail('test@example.com')
// Assert
expect(result).toEqual(mockUser)
})
})
Mocking Patterns
For detailed mocking patterns including variable ordering, beforeEach setup, and ModuleMocker usage, see references/mocking-patterns.md.
Cleanup
Always clean up side effects after each test:
afterEach(async () => {
await moduleMocker.clear() // restore mocked modules
vi.clearAllMocks() // or mock.mockClear() for individual mocks
})