Testing
هذا المحتوى غير متوفر بلغتك بعد.
Testing
Section titled “Testing”What is tested, how endpoint tests run against real infrastructure, and the helpers the framework provides.
Requirements
Section titled “Requirements”bun run db:up # PostgreSQL :54329 + Redis :63799 (compose)cp .env.test.example .env.test # TEST_DATABASE_URL=postgres://… (a server-level admin URL)TEST_DATABASE_URL must point at a dedicated test server/admin URL —
never the application’s DATABASE_URL; the testing package refuses to
create test databases on the application target or in APP_ENV=production.
Isolated databases
Section titled “Isolated databases”Every database test gets its own database (fw_test_<random>), created from
TEST_DATABASE_URL, migrated from the app’s database/migrations, and
dropped in success and failure paths. Nothing leaks between runs.
Application-level tests use the generated tests/support.ts:
const ctx = await createTestContext(); // boots the full app on a fresh migrated DBconst response = await ctx.client.request('/api/v1/products', jsonInit('POST', { name: 'x', price: '1' }));await ctx.close(); // stops server, shuts down, drops the DBTEST_MODE=network swaps in-process http.request for a real loopback
listener (same assertions, real transport). The generated endpoint suites
run identically in both modes — make:crud --verify --test-mode network
proves routes over the wire.
What the generated suites cover
Section titled “What the generated suites cover”Each make:crud module ships tests/<resource>.crud.api.test.ts, which
calls the registered Hono application (never a mocked controller):
- happy path: create → list → read → update → re-read → delete → 404
- public allowlist exposure (secret fields never serialized)
- deterministic, bounded listing; pagination bounds (422)
- malformed JSON (400), malformed ids (422), unknown ids (404)
- invalid payloads: missing / mistyped / refinement-violating / forbidden fields
- empty updates, immutable fields (
createdAt)
make:crud --verify runs this suite plus a typecheck after every generation
and reports each route, pass/fail counts and database cleanup in the result
(JSON with --json).
Framework package tests
Section titled “Framework package tests”Package tests (packages/*/tests) exercise real adapters where it matters:
CRUD mixins, auditing, transactions and pagination run on real PostgreSQL;
queues run on real Redis; events tests cover both buses. Pattern:
const database = await createTestDatabase({ adminUrl: requireTestDatabaseUrl() });const connection = createConnection({ url: database.url, maxConnections: 4 });await connection.sql`create table …`;// … assertions …await connection.close();await database.drop();Fakes — and their limits
Section titled “Fakes — and their limits”MemoryEventBus stands in for Redis in unit tests; the testing package
provides isolated databases instead of a fake query layer. Fakes prove
wiring, never infrastructure behavior — retry, duplicate delivery and
failure semantics are only proven by the real-adapter suites.
Generator and release gates
Section titled “Generator and release gates”packages/cli/tests/generated-app.test.ts—make:crudend to end on new and existing tables, route collisions,--dry-runwriting nothing, and the generated application’s full suite.packages/cli/tests/create-app.test.ts— thecreaterelease gate: the generated application typechecks, passes its suite, migrates the audit table, acceptsmake:crud --verify, andcreate --with-demoproduces a working products module whose endpoint tests pass as-is.apps/playground/tests/contract.test.ts— OpenAPI drift check and a typed Hono RPC client against the composed application.
Run everything from the workspace root:
bun test # or: bun run testConventions
Section titled “Conventions”- No skipped-if-missing tests: missing
TEST_DATABASE_URLfails with setup instructions instead of silently passing. - Tests never auto-migrate the application database; they only migrate their own isolated database.
- Ephemeral network servers bind
127.0.0.1:0and always close.