Test DOs in-process
White-box Durable Object tests with composeDurableInstance and fake state helpers.
Flare ships in-process helpers to exercise Durable Object routes without deploying to workerd. Import them from @flare-ts/core/cloudflare (the module needs a Workers environment: it imports cloudflare:workers at module scope). composeDurableInstance takes the built host.
composeDurableInstance
Section titled “composeDurableInstance”import { composeDurableInstance, DurableState, FlareDurableObject, makeEnv, makeFakeDurableState,} from "@flare-ts/core/cloudflare";import { FlareHost, FlareResponse, FlareService } from "@flare-ts/core";import { cf } from "@flare-ts/core/cloudflare";
class Counter extends FlareService { public static override deps = []; #n = 0; bump() { this.#n += 1; }}
class Room extends FlareDurableObject { public static override deps = [DurableState, Counter] as const;}
const host = new FlareHost(cf);host.scoped(Counter);const room = host.durableObject(Room);
room.http.get( "/ping", { inject: { ds: DurableState } }, (_ctx, scope) => new FlareResponse(200, { id: scope.ds.id.toString() }),);
host.http.get("/_", () => new FlareResponse(200)); // Worker front door needs at least one route
host.build();
const inst = composeDurableInstance( host, makeFakeDurableState({ name: "room-1" }), makeEnv({ REGION: "enam" }), Room,);
const res = await inst.fetch(new Request("https://do/ping"));expect(res.status).toBe(200);composeDurableInstance bypasses the real DO constructor (workerd owns that) and composes the per-instance container and DurableHandler you can drive with inst.fetch().
Resolve services
Section titled “Resolve services”// The first argument is the DO class's `static deps` allow-list; Counter is// listed in Room's `static deps` above.const counter = inst.inject(Room.deps, Counter);counter.bump();Use this to unit-test services wired through the DO’s scoped container.
Fake storage
Section titled “Fake storage”makeFakeDurableState accepts options including in-memory storage from makeFakeStorage():
const storage = makeFakeStorage();const state = makeFakeDurableState({ name: "room-1", storage });makeFakeStorage() covers only the KV subset (get, put, delete, list). No SQL: DOs that use state.storage.sql need a real cloudflare:test binding.
WebSocket routes
Section titled “WebSocket routes”Drive WebSocket routes through inst.fetch() with an upgrade Request under the cloudflare:test pool: the upgrade allocates a WebSocketPair, a Workers-runtime global. res.webSocket on the 101 response is the client half of the pair. Use a real cloudflare:test binding when you need the real constructor, alarm, or RPC methods.
Related
Section titled “Related”- Testing overview:
FLARE_MODE=testandapp.test() - Test WebSockets and DO: broader WS + DO testing
- Overview: registration model