@j0nathan-ll0yd/testing
Lambda context mocks, entity mocks, event fixtures, and auth mocks for Vitest.
The package root exports the helpers below. Deeper APIs live at subpath imports: ./lambda-mocks, ./entity-mocks, ./aws-mocks, ./fixtures, ./auth-mocks, ./integration, and ./vitest-setup.
Vitest Setup
Add the setup file to your Vitest config. It auto-mocks every @j0nathan-ll0yd/observability export, so tests never need to stub the logger, metrics, or tracer by hand.
// vitest.config.ts
export default defineConfig({
test: { setupFiles: ["@j0nathan-ll0yd/testing/vitest-setup"] },
});Lambda Mocks
createMockContext(overrides?)
Build a Lambda Context with realistic defaults. Override any field.
import { createMockContext } from "@j0nathan-ll0yd/testing";
const context = createMockContext({
functionName: "ListFiles",
getRemainingTimeInMillis: () => 5000,
});createMockApiEvent(overrides?)
Build an APIGatewayProxyEvent. Supply only the parts the handler reads.
import { createMockApiEvent } from "@j0nathan-ll0yd/testing";
const event = createMockApiEvent({
httpMethod: "POST",
path: "/files",
headers: { Authorization: "Bearer test-token" },
body: JSON.stringify({ fileId: "abc" }),
});createObservabilityMock()
Return a ready-made mock module for @j0nathan-ll0yd/observability, for tests that need to assert on log or metric calls rather than merely silence them.
import { createObservabilityMock } from "@j0nathan-ll0yd/testing";
vi.mock("@j0nathan-ll0yd/observability", () => createObservabilityMock());Entity Mocks
Mock a query module without restating its shape in every test file. Every mock created through these helpers is registered, so one call resets or clears them all.
createEntityMock(methods)
Build a mock from a list of method names.
import { createEntityMock } from "@j0nathan-ll0yd/testing";
const files = createEntityMock<typeof import("../src/db/files.js")>(["getFile", "listFiles"]);
files.getFile.mockResolvedValue({ fileId: "abc" });createEntityMockFrom(shape)
Build a mock from the real module object, so a method added upstream appears in the mock automatically.
import * as fileQueries from "../src/db/files.js";
const files = createEntityMockFrom(fileQueries);Both return a MockedEntity<T>: every function property becomes a Vitest Mock with the original signature.
resetAllEntityMocks()
Reset call history and implementations on every registered entity mock. Call from beforeEach.
clearAllEntityMocks()
Clear call history on every registered entity mock, leaving implementations in place.
Event Fixtures
Build valid AWS event payloads without hand-writing envelope fields.
| Builder | Returns |
|---|---|
buildSqsEvent(records) | SQSEvent |
buildEventBridgeEvent(options) | EventBridgeEvent<TDetailType, TDetail> |
buildS3Event(records) | S3Event |
buildScheduledEvent(options?) | ScheduledEvent |
buildWebSocketEvent(options) | APIGatewayProxyWebsocketEventV2 |
import {
buildEventBridgeEvent,
buildS3Event,
buildScheduledEvent,
buildSqsEvent,
buildWebSocketEvent,
} from "@j0nathan-ll0yd/testing";
const sqs = buildSqsEvent([{ body: { fileId: "abc" } }]); // bodies are JSON-serialized for you
const eb = buildEventBridgeEvent({ detailType: "FileUploaded", detail: { fileId: "abc" } });
const s3 = buildS3Event([{ bucket: "uploads", key: "a/b.json", size: 128 }]);
const scheduled = buildScheduledEvent({
ruleArn: "arn:aws:events:us-east-1:123456789012:rule/daily",
});
const ws = buildWebSocketEvent({ routeKey: "$connect", connectionId: "conn-1" });Auth Mocks
createAuthMock(options?)
Return a Better Auth double exposing api.getSession, api.signInSocial, api.revokeSession, and handler. Pass { session } to preset what getSession resolves to; pass { session: null } for the unauthenticated case.
import { createAuthMock, createSessionResult } from "@j0nathan-ll0yd/testing";
const auth = createAuthMock({ session: createSessionResult() });createSessionResult(overrides?)
Build a SessionResult with a valid user and session. Accepts partial user and session overrides.
createUserDetails(overrides?)
Build a UserDetails object on its own, for tests that need the user but not a session.
Integration Timeouts
TIMEOUTS
Named timeout budgets in milliseconds, shared by every integration suite so no test invents its own number. Each value is larger under CI, where runners are slower.
import { TIMEOUTS } from "@j0nathan-ll0yd/testing";
it(
"delivers the event",
async () => {
// ...
},
TIMEOUTS.eventDelivery,
);Keys: serviceReady, eventBridgeReady, sqsMessage, sqsMultipleMessages, schemaCreation, dbConnection, eventDelivery, snsOperation, s3Operation, singleTest, e2eTest, hookTimeout.