AWS 持久执行测试 JavaScript SDK
测试 JavaScript 和 TypeScript 的 AWS 持久执行 SDK 工具 .
特征
该软件包为本地和云中的持久功能提供了测试工具:
-
本地可调试运行器 - 在不部署AWS的情况下在当地执行和测试持久功能
- 耗时支持 - 跳过等待操作并延迟更快的测试执行
- 职能登记 - 登记链式援引测试的其他功能
- 全面业务检查 - 获取关于步骤、等待、回调和更多步骤的详细资料
- 爱嘲笑 - 与杰斯特和其他嘲弄框架无缝合作
-
云可控试跑器 - 测试已部署的AWS Lambda功能
- 真实环境测试 - 对照实际部署的AWS Lambda功能验证行为
- 定性援引 - 支持不同的援引类型和投票间隔
-
测试能力
- 行动断言 - 按名称、索引或身份证检查个人操作
- 现状和结果验证 - 核查执行状况、结果和错误条件
- 回调测试 - 发出回调回复并核实回调行为
- 重试验证 - 测试步骤重试逻辑和失败情况
-
长期运行的CLI - 无需写出测试代码即可快速测试的命令行工具
- 零设置 - 运行任何持久功能
npx run-durable your-function.js - 行动检查 - 查看详细的操作表和执行记录
- 时间控制 - 缩短快速测试时间或使用真实的验证时间
- 零设置 - 运行任何持久功能
安装
npm install --save-dev @aws/durable-execution-sdk-js-testing
快速启动
处理器代码
import {
withDurableExecution,
DurableContext,
} from "@aws/durable-execution-sdk-js";
const handler = async (event: any, context: DurableContext) => {
// Execute a durable step with automatic retry
const userData = await context.step("fetch-user", async () =>
fetchUserFromDB(event.userId),
);
// Wait for 5 seconds
await context.wait({ seconds: 5 });
// Process data in another step
const result = await context.step("process-user", async () =>
processUser(userData),
);
return result;
};
export const lambdaHandler = withDurableExecution(handler);
测试代码
本地测试
import {
LocalDurableTestRunner,
WaitingOperationStatus,
} from "@aws/durable-execution-sdk-js-testing";
import { lambdaHandler } from "./lambdaHandler";
beforeAll(() =>
LocalDurableTestRunner.setupTestEnvironment({
skipTime: true,
}),
);
afterAll(() => LocalDurableTestRunner.teardownTestEnvironment());
describe("LocalDurableTestRunner", () => {
let runner;
beforeEach(() => {
runner = new LocalDurableTestRunner({
handlerFunction: lambdaHandler,
});
});
it("should wait for 5 seconds and return result", async () => {
const execution = await runner.run({ payload: { userId: "123" } });
expect(execution.getStatus()).toBe("SUCCEEDED");
expect(execution.getOperations()).toHaveLength(3); // fetch-user, wait, process-user
// Check the fetch-user step
const fetchStep = runner.getOperation("fetch-user");
await fetchStep.waitForData(WaitingOperationStatus.COMPLETED);
const fetchDetails = fetchStep.getStepDetails();
expect(fetchDetails?.result).toBeDefined();
// Check the wait operation
const waitOp = runner.getOperationByIndex(1);
const waitDetails = waitOp.getWaitDetails();
expect(waitDetails?.waitSeconds).toBe(5);
// Check the process-user step
const processStep = runner.getOperation("process-user");
await processStep.waitForData(WaitingOperationStatus.COMPLETED);
const processDetails = processStep.getStepDetails();
expect(processDetails?.result).toBeDefined();
});
});
云测试
import {
CloudDurableTestRunner,
WaitingOperationStatus,
} from "@aws/durable-execution-sdk-js-testing";
describe("CloudDurableTestRunner", () => {
let runner;
beforeEach(() => {
runner = new CloudDurableTestRunner({
functionName: "my-durable-function", // Your deployed function name
});
});
it("should wait for 5 seconds and return result", async () => {
const execution = await runner.run({ payload: { userId: "123" } });
expect(execution.getStatus()).toBe("SUCCEEDED");
expect(execution.getOperations()).toHaveLength(3); // fetch-user, wait, process-user
// Check the fetch-user step
const fetchStep = runner.getOperation("fetch-user");
const fetchDetails = fetchStep.getStepDetails();
expect(fetchDetails?.result).toBeDefined();
expect(fetchDetails?.attempt).toBe(1);
// Check the wait operation
const waitOp = runner.getOperationByIndex(1);
const waitDetails = waitOp.getWaitDetails();
expect(waitDetails?.waitSeconds).toBe(5);
// Check the process-user step
const processStep = runner.getOperation("process-user");
const processDetails = processStep.getStepDetails();
expect(processDetails?.result).toBeDefined();
});
});
文档
这个README为测试SDK的主要功能提供了快速的参考. 详细情况:
- API 参考 - 附有详细类型定义和操作规格的完整技术参考
- 持续运行的 CLI 指南 - 使用命令行工具快速测试持久功能的完整指南
- 捐款 - 学习如何为JavaScript的AWS持久执行测试SDK做出贡献
本地可调试运行器
以模拟可持久执行后端在本地运行可持久功能.
import { LocalDurableTestRunner } from "@aws/durable-execution-sdk-js-testing";
import { handler } from "./my-durable-function";
// Set up test environment with optional time skipping
await LocalDurableTestRunner.setupTestEnvironment({
skipTime: true, // Skip wait delays for faster tests
});
const runner = new LocalDurableTestRunner({
handlerFunction: handler,
});
const execution = await runner.run({ payload: { test: "data" } });
// Assert on results
expect(execution.getStatus()).toBe("SUCCEEDED");
expect(execution.getResult()).toEqual(expectedValue);
// Assert on operations
const operations = execution.getOperations();
expect(operations).toHaveLength(3);
// Clean up test environment
await LocalDurableTestRunner.teardownTestEnvironment();
嘲笑
使用 Jest 或您喜欢的测试框架模拟外部依赖性 :
import { LocalDurableTestRunner } from "@aws/durable-execution-sdk-js-testing";
// Mock external functions
jest.mock("../services/userService", () => ({
fetchUserFromDB: jest.fn(),
processUser: jest.fn(),
}));
import { fetchUserFromDB, processUser } from "../services/userService";
import { lambdaHandler } from "./lambdaHandler";
const mockFetchUser = fetchUserFromDB as jest.MockedFunction<
typeof fetchUserFromDB
>;
const mockProcessUser = processUser as jest.MockedFunction<typeof processUser>;
describe("Mocked Dependencies", () => {
let runner: LocalDurableTestRunner;
beforeAll(() =>
LocalDurableTestRunner.setupTestEnvironment({ skipTime: true }),
);
afterAll(() => LocalDurableTestRunner.teardownTestEnvironment());
beforeEach(() => {
runner = new LocalDurableTestRunner({ handlerFunction: lambdaHandler });
// Reset mocks
mockFetchUser.mockClear();
mockProcessUser.mockClear();
});
it("should call mocked functions and return expected results", async () => {
// Setup mocks
const userData = { id: "123", name: "John Doe" };
const processedResult = { id: "123", processed: true };
mockFetchUser.mockResolvedValue(userData);
mockProcessUser.mockResolvedValue(processedResult);
// Run test
const execution = await runner.run({ payload: { userId: "123" } });
// Verify results
expect(execution.getStatus()).toBe("SUCCEEDED");
expect(execution.getResult()).toEqual(processedResult);
// Verify mock calls
expect(mockFetchUser).toHaveBeenCalledWith("123");
expect(mockProcessUser).toHaveBeenCalledWith(userData);
// Verify operations
const fetchStep = runner.getOperation("fetch-user");
const fetchDetails = fetchStep.getStepDetails();
expect(fetchDetails?.result).toEqual(userData);
});
});
函数注册
注册本地测试链式引用时可以引用的额外功能 :
处理器代码
const mainHandler = withDurableExecution(async (event, context) => {
await context.invoke("workflow-a:$LATEST");
await context.invoke("workflow-b:$LATEST");
await context.invoke("utility-function");
await context.invoke("utility-helper");
});
测试代码
const runner = new LocalDurableTestRunner({ handlerFunction: mainHandler });
// Register durable functions
runner.registerDurableFunction("workflow-a:$LATEST", durableWorkflowA);
// Register regular functions
runner.registerFunction("utility-function", utilityHandler);
// Method chaining is supported
runner
.registerDurableFunction("workflow-b:$LATEST", durableWorkflowB)
.registerFunction("helper", helperHandler);
云可控试跑器
测试在AWS中部署的Lambda功能.
import {
CloudDurableTestRunner,
InvocationType,
} from "@aws/durable-execution-sdk-js-testing";
import { LambdaClient } from "@aws-sdk/client-lambda";
const runner = new CloudDurableTestRunner({
functionName: "MyDurableFunction",
client: new LambdaClient({ region: "us-east-1" }), // optional
config: {
pollInterval: 1000, // optional, default 1000ms
invocationType: InvocationType.RequestResponse, // optional
},
});
const execution = await runner.run({ payload: { userId: "123" } });
expect(execution.getStatus()).toBe("SUCCEEDED");
测试结果 API
两个跑者返回a TestResult 有断言方法的物体:
const execution = await runner.run();
// Get execution status and results
execution.getStatus(); // "SUCCEEDED" | "FAILED" | "RUNNING" | etc.
execution.getResult(); // Returns the function result
execution.getError(); // Returns error details if failed
// Get operations
execution.getOperations(); // All operations
execution.getOperations({ status: "SUCCEEDED" }); // Filter by status
// Get execution history and invocations
execution.getHistoryEvents(); // Detailed event history
execution.getInvocations(); // Handler invocation details
// Print operations table to console
execution.print(); // Default columns
execution.print({ name: true, status: true, duration: true }); // Custom columns
请求行动
获取具体操作,以便详细断言:
// Get operations by different methods
const operation = runner.getOperation("my-step"); // By name
const firstOp = runner.getOperationByIndex(0); // By execution order
const secondNamedOp = runner.getOperationByNameAndIndex("my-step", 1); // By name + index
const opById = runner.getOperationById("abc123"); // By unique ID
// Wait for operation data to be available
await operation.waitForData(); // Default to STARTED status
await operation.waitForData(WaitingOperationStatus.COMPLETED);
// Get operation details based on type
const stepDetails = operation.getStepDetails(); // For step operations
const contextDetails = operation.getContextDetails(); // For context operations
const callbackDetails = operation.getCallbackDetails(); // For callback operations
const waitDetails = operation.getWaitDetails(); // For wait operations
// Get basic operation information
operation.getName();
operation.getStatus();
operation.getStartTimestamp();
operation.getEndTimestamp();
回调操作
对于回调操作,您可以发送回复:
const callback = runner.getOperation("my-callback");
await callback.waitForData(WaitingOperationStatus.SUBMITTED);
// Send callback responses
await callback.sendCallbackSuccess("result data");
await callback.sendCallbackFailure({ errorMessage: "Failed" });
await callback.sendCallbackHeartbeat();
配置选项
本地可调试运行器
// Constructor
new LocalDurableTestRunner({ handlerFunction: handler });
// Environment setup
await LocalDurableTestRunner.setupTestEnvironment({ skipTime: true });
// Environment teardown
await LocalDurableTestRunner.teardownTestEnvironment();
云可控试跑器
// Basic configuration
new CloudDurableTestRunner({ functionName: "MyFunction:$LATEST" });
// Advanced configuration
new CloudDurableTestRunner({
functionName: "MyFunction:$LATEST",
client: new LambdaClient({ region: "us-east-1" }),
config: { pollInterval: 500, invocationType: InvocationType.Event },
});
重置运行状态
这个 reset() 如果在测试之间重复使用同样的跑道实例,则需要方法。 有关个人被处决的数据,当 reset() 名为.
describe("Reusing Runner Instance", () => {
let runner: LocalDurableTestRunner;
beforeAll(() => {
// Create runner once
runner = new LocalDurableTestRunner({ handlerFunction: handler });
});
beforeEach(() => {
// Reset state when reusing the same instance
runner.reset();
});
// ... tests
});
警卫
见 捐款 更多信息.
许可证
这个项目根据Apache-2.0许可证获得许可证.