Stacks Testing
Uses Bun's built-in test runner with Stacks-specific test utilities.
This skill is the mechanics: the utilities, the setup, the CLI, the gotchas.
stacks-tdd is the discipline: the red-green loop, which seam a test belongs
at, and the anti-patterns that make a test worse than no test. Read that one
before deciding what to test, and this one for how.
Key Paths
- Core package:
storage/framework/core/testing/src/ - Test directory:
tests/ - Test setup:
tests/setup.ts - Package:
@stacksjs/testing
Test Setup
import { setupTestEnvironment, setupDatabase, refreshDatabase } from '@stacksjs/testing'
// Set NODE_ENV and APP_ENV to 'test'
setupTestEnvironment()
// Create testing database (SQLite: database/stacks_testing.sqlite)
await setupDatabase()
// Refresh database (drop and re-migrate)
await refreshDatabase()
// Truncate tables
await truncateSqlite() // for SQLite
await truncateMysql() // for MySQL
DynamoDB Testing
import { launchServer, createStacksTable, deleteStacksTable, delay } from '@stacksjs/testing'
// Launch DynamoDB Local
const { server, endpoint } = await launchServer()
// Create test table
await createStacksTable()
// Cleanup
await deleteStacksTable()
// Utility
await delay(1000) // wait for async operations
Writing Tests
import { describe, test, it, expect, beforeAll, afterAll, beforeEach } from 'bun:test'
describe('User Model', () => {
beforeAll(async () => {
await setupDatabase()
})
afterAll(async () => {
await refreshDatabase()
})
test('can create a user', async () => {
const user = await User.create({ name: 'John', email: 'john@test.com' })
expect(user.name).toBe('John')
})
test('validates email uniqueness', async () => {
await expect(User.create({ email: 'duplicate@test.com' }))
.rejects.toThrow()
})
})
Queue Testing
import { fake, restore, runTestJob, expectJobToFail } from '@stacksjs/queue'
test('dispatches welcome email job', async () => {
const fakeQueue = fake()
await SendWelcomeEmail.dispatch({ email: 'test@test.com' })
fakeQueue.assertDispatched('SendWelcomeEmail')
restore()
})
CLI Commands
buddy test # run all tests
buddy test --unit # unit tests only
buddy test --feature # feature tests only
bun run test # via npm script
bun run test:ui # UI tests
bun run test:coverage # with coverage
bun run test:types # type tests
Configuration (bunfig.toml)
[test]
preload = ["./tests/setup.ts"]
Test File Conventions
- Test files:
*.test.tsor*.spec.ts - Located in
tests/directory - Setup/teardown in
tests/setup.ts - Unit tests in
tests/unit/ - Feature tests in
tests/feature/
Gotchas
- Uses Bun's native test runner, NOT Jest or Vitest
- Test preload runs
tests/setup.tsbefore each test file - SQLite testing database is at
database/stacks_testing.sqlite refreshDatabase()drops ALL tables - use in test setup only- DynamoDB Local must be installed for DynamoDB tests
- Queue testing uses
fake()/restore()pattern - affects global state @stacksjs/fakerprovides test data generation- Coverage reports with
bun run test:coverage
Downstream
Deciding what to test, or where?
/stacks-tdd. Reviewing someone else's tests?/stacks-reviewaudits coverage as its third pass.