Skip to content
RELKIT
Esc
↑↓navigate↵open⌘Jpreview
On this page

Testing

Test functions and in-process routes, then verify production transport behavior against a running backend.

Choose the test boundary that proves the behavior: a function, an application, or a running HTTP server. Function tests exercise one descriptor without a server. Application tests load checked configuration and call an in-process HTTP client. Neither layer needs remote credentials when provider-backed capabilities receive explicit fakes. Use a running backend for final HTTP middleware, origin, cookie, and transport behavior.

Install the selected test tooling

The minimal starter already has development-only @relkit/testing. In another existing app, install it explicitly before copying these tests:

From this guide’s application/package root, install only its selected requirements:

bun add --dev @relkit/testing@0.8.1

Keep these owner-specific versions and the lockfile together. Runtime SDKs belong in dependencies; build/type tooling belongs in devDependencies. Installing an adapter does not supply its optional SDK peers or enable the feature’s configuration.

The generic harness installs no optional database, authentication or model SDK. Keep feature adapters and native SDKs in the application’s selected runtime dependencies. Use @relkit/testing/drizzle for database tests, @relkit/testing/better-auth for database-backed auth, and native agent helpers from @relkit/langchain or @relkit/langchain/testing after agent setup.

Test one function

Use invokeFunction for input and output validation, declared errors, nested invocation, and handler behavior:

/** Checks orders.function through the supported public RELKIT APIs. */
import { expect, test } from "bun:test";
import { invokeFunction } from "@relkit/testing";
import orders from "@app/services/orders/service.js";

test("createOrder invokes pricing", async () => {
  const result = await invokeFunction(orders.createOrder, {
    orderId: "order-1",
    sku: "book",
    quantity: 3,
  });

  expect(result).toEqual({ orderId: "order-1", sku: "book", totalCents: 300 });
});
bun test tests/unit/orders.function.test.ts

Pass test clients when the function declares cache, bucket, job, or event capabilities. Agent tests should declare or inject a deterministic native LangChain model and inspect recorded effects instead of sleeping or calling a live service.

Test the application boundary

Use createTestApplication for discovered routes, mapped input, function invocation, and provider wiring. The Orders tutorial test also migrates isolated SQLite and checks two users’ ownership boundary. The starter’s smallest HTTP test is:

import { afterAll, expect, test } from "bun:test";
import { createTestApplication } from "@relkit/testing";
import config from "../../relkit.config.js";

const testApp = await createTestApplication(config, { resourceProviders: "fake" });

test("POST /orders", async () => {
  const response = await testApp.http.request("/orders", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ orderId: "order-1", sku: "book", quantity: 3 }),
  });
  expect(response.status).toBe(201);
  expect(await response.json()).toEqual({
    orderId: "order-1",
    sku: "book",
    totalCents: 300,
  });
});

afterAll(() => testApp.close());

The harness runs in process and exposes application.http. It maps invalid function input to a validation 422, but it does not implement the entire production HTTP pipeline. It does not prove all middleware, rate limits, OpenAPI behavior, or RPC transport. Close it in afterAll so runtime state and handles do not leak into another test, then send representative requests to the running backend as the Start journey does.

Replace provider profiles explicitly

The commerce suite shows the complete shape for cache, bucket, realtime, and agent-state profiles alongside native model execution:

Complete commerce HTTP test

Every graph-required capability and profile must have a replacement. RELKIT_ENV=test does not silently select fakes. Use createTestCacheFake and createTestBucketFake for deterministic resource behavior, and dedicated test event, job, or agent utilities for those contracts.

Run the application gate

bun run test
bun run check
bun run typecheck
bun run build

Keep live integration and cloud tests separate and opt-in. In the RELKIT repository, bun run prepush runs the focused merge-blocking checks without Docker; bun run prepush:full includes Docker acceptance.

Task-first jobs add focused unit, type, contract, restart, client, Inspector, Docker, and provider suites. The Docker/provider commands are explicit gates; managed cloud acceptance remains separately authorized.

Reference and source