Anvil Cloud / Runtime
Testing Cells
Anvil Cloud is designed to be testable without a cloud provider. The runtime package includes in-memory adapters so you can write fast, deterministic tests against the same contract used in production.
In-memory runtime host
@anvil-cloud/runtime exports createInMemoryRuntimeHost():
import { createInMemoryRuntimeHost } from "@anvil-cloud/runtime";
const host = createInMemoryRuntimeHost({
auth: { userId: "test-user", roles: ["admin"] }
});
The in-memory host provides:
- In-memory database with full
whereclause support. - In-memory file storage.
- Captured log entries.
- Tracked events and enqueued jobs.
- Configurable auth identity.
Testing a query
import { handleRuntimeRequest } from "@anvil-cloud/runtime";
const request = {
kind: "query" as const,
name: "listTodos",
input: {},
auth: { userId: "test-user" },
requestId: "req-1"
};
const response = await handleRuntimeRequest({
app: myApp,
request,
host
});
assert(response.ok === true);
assert(Array.isArray(response.body));
Testing a mutation
const request = {
kind: "mutation" as const,
name: "addTodo",
input: { text: "Test todo" },
auth: { userId: "test-user" },
requestId: "req-2"
};
const response = await handleRuntimeRequest({ app: myApp, request, host });
assert(response.ok === true);
assert(response.body.text === "Test todo");
Inspecting side effects
After a request, inspect the host directly:
// Check database state
const todos = await host.db.todos.all();
assert(todos.length === 1);
// Check logs
assert(host.logs.some(l => l.message.includes("Test todo")));
// Check events
assert(host.events.some(e => e.name === "todo.created"));
// Check jobs
assert(host.jobs.some(j => j.name === "notifyUser"));
Testing auth
// Unauthenticated request
const guestHost = createInMemoryRuntimeHost({ auth: null });
const response = await handleRuntimeRequest({
app: myApp,
request: { kind: "query", name: "listTodos", input: {}, auth: null, requestId: "req-3" },
host: guestHost
});
assert(response.ok === false);
assert(response.error?.code === "AUTH_REQUIRED");
Testing capabilities
If a handler uses ctx.files.put but the Cell does not declare capabilities.files, the runtime returns CAPABILITY_NOT_DECLARED:
const response = await handleRuntimeRequest({ ... });
assert(response.error?.code === "CAPABILITY_NOT_DECLARED");
Test recommendations
- Test happy paths and auth failures.
- Test capability mismatches.
- Assert on side effects through the host adapters, not by mocking implementation details.
- Keep tests fast: in-memory adapters are synchronous where possible.
- Run
anvil check --jsonin CI before running tests to catch import policy and type errors early.