Testing
FLARE_MODE=test, app.test(), service replacement, and @flare-ts/core/testing helpers.
Flare integration tests drive the same composed app production uses. Set FLARE_MODE=test before the host module loads and host.build() returns a test app. Call app.test() to get a TestAppHandle that sends synthetic requests through the real HTTP pipelines in-process. No listen port is bound.
Unit tests construct controllers and services directly with mockContext and mockContainer from @flare-ts/core/testing. WebSocket arcs validate in-process at host.build(); Durable Objects compose an instance in-process with composeDurableInstance and the KV-only fakes from @flare-ts/core/cloudflare.
Testing
Section titled “Testing”- Write your first test: FLARE_MODE=test, app.test(), handle.fetch, and asserting on a real Response.
- Replace services in tests: Swap a registered service with a test double via replace on test() or reset().
- Unit-test a controller: mockContext and mockContainer for one method in isolation, no HTTP pipeline.
- Inspect the build graph: inspectBuild snapshots of host registrations, the compiled router, and pipelines.
- Test WebSockets and Durable Objects: In-process WebSocket arc validation and composeDurableInstance for Durable Objects.
Test mode setup
Section titled “Test mode setup”Set FLARE_MODE=test before the host module is imported. The Node and Cloudflare adapters read it from process.env (or the adapter env object). Without it, host.build() returns a production runtime app and app.test() throws.
import { defineConfig } from "vitest/config";
export default defineConfig({ test: { env: { FLARE_MODE: "test" }, },});Export host as a named export from a module your tests import. Under test mode, app.run() and app.export() are no-op shims (no socket bind, no real handler export).
What the integration path exercises
Section titled “What the integration path exercises”TestAppHandle.fetch walks routing, middleware, error handlers, serializers, and route contracts. It skips only the socket bind and the long-lived process. Singleton instantiation is deferred to app.test() (scoped services build per request), so replace can substitute classes before any constructor runs.
The failure this design avoids is drift between what tests exercise and what production runs. A test that calls a handler function directly with mocked arguments validates the business logic while bypassing routing, contracts, middleware, and DI wiring, so it stays green when a route is mismounted or a contract rejects real traffic. handle.fetch runs the same compiled pipelines production serves, so those mistakes fail tests instead of surviving them.
Lower-level helpers
Section titled “Lower-level helpers”Import from @flare-ts/core/testing:
| Export | Use |
|---|---|
TestAppHandle | Integration handle from app.test() |
inspectBuild | Read-only build snapshot |
mockContainer | Fake DI container for unit tests |
mockContext | Synthetic FlareHttpContext |
FlareTestError | Harness setup failures (not app HTTP errors) |
See the API Reference for AppTestOptions, snapshot types, and TestRequestInit.