Documentation Index
Fetch the complete documentation index at: https://docs.restate.dev/llms.txt
Use this file to discover all available pages before exploring further.
The Typescript SDK has a companion library which makes it easy to test against a Restate container:
@restatedev/restate-sdk-testcontainers.
This uses Testcontainers to run a Restate Server in a Docker container and let you test your Restate handlers.
Setup
RestateTestEnvironment.start creates a Restate container and executes a user-provided closure to register services.
An optional second argument allows you to specify a custom Testcontainer for Restate.
describe("ExampleObject", () => {
// import { RestateTestEnvironment } from "@restatedev/restate-sdk-testcontainers";
let restateTestEnvironment: RestateTestEnvironment;
// import * as clients from "@restatedev/restate-sdk-clients";
let restateIngress: clients.Ingress;
beforeAll(async () => {
restateTestEnvironment = await RestateTestEnvironment.start({
services: [router],
});
restateIngress = clients.connect({ url: restateTestEnvironment.baseUrl() });
}, 20_000);
afterAll(async () => {
if (restateTestEnvironment !== undefined) {
await restateTestEnvironment.stop();
}
});
Calling services
The Restate ingress client can be used as usual (see the clients documentation)
it("Can call methods", async () => {
const client = restateIngress.objectClient(router, "myKey");
await client.greet("Test!");
});
Checking and mutating state
The stateOf method on the RestateTestEnvironment class can be used to obtain a handle on the Virtual Object / Workflow state
for a particular key.
it("Can read state", async () => {
const state = restateTestEnvironment.stateOf(router, "myKey");
expect(await state.getAll()).toStrictEqual({});
expect(await state.get("count")).toBeNull();
});
it("Can write state", async () => {
const state = restateTestEnvironment.stateOf(router, "myKey");
await state.setAll({
count: 123,
});
await state.set("count", 321);
});
Typed state
stateOf can be provided with a type for the services state, to allow for type-safe state operations.
type ServiceState = { count: number };
it("Can operate on typed state", async () => {
const state = restateTestEnvironment.stateOf<ServiceState>(router, "myKey");
await state.setAll({ count: 1 });
await state.set("count", 2);
});
Testing non-determinism bugs
Forces Restate to replay the handler on every suspension point. Use this to hunt non-determinism bugs. If your handler is not replay-safe, this will surface the issue:
describe("with alwaysReplay", () => {
let env: RestateTestEnvironment;
beforeAll(async () => {
env = await RestateTestEnvironment.start({
services: [router],
alwaysReplay: true,
});
}, 20_000);
afterAll(async () => env?.stop());
it("replays after every suspension", async () => {
// handler logic here
});
});
Disabling retries
Disabling Restate’s built-in retry policy lets you surface failures immediately instead of hanging through retry backoff. Useful when testing error paths in your handlers:
describe("with disableRetries", () => {
let env: RestateTestEnvironment;
beforeAll(async () => {
env = await RestateTestEnvironment.start({
services: [router],
disableRetries: true,
});
}, 20_000);
afterAll(async () => env?.stop());
it("fails immediately without retry backoff", async () => {
// handler logic here
});
});