如何为V4版JavaScript Azure Durable Function编写单元测试?
Azure Durable Functions V4(JavaScript)单元测试指南
适用的测试工具
- 官方适配库:
@azure/durable-functions-testing,专为Durable Functions V4版本设计,提供编排器测试的模拟执行环境 - 测试框架:使用
jest或mocha编写测试用例 - Mock工具:
sinon用于模拟上下文、Durable Client等依赖项
测试编排器(AutoDeleteBackupOrchestrator)
编排器是生成器函数,需借助DurableOrchestrationTestHarness模拟执行流程,捕获并验证活动函数的调用逻辑。
示例测试代码
const { DurableOrchestrationTestHarness } = require('@azure/durable-functions-testing'); const df = require('durable-functions'); // 导入包含编排器的模块 const orchestratorModule = require('./path/to/your/orchestrator/file'); describe('AutoDeleteBackupOrchestrator', () => { let harness; beforeEach(() => { // 初始化测试环境 harness = new DurableOrchestrationTestHarness(df.app); // 注册目标编排器 harness.addOrchestrator('AutoDeleteBackupOrchestrator', orchestratorModule.AutoDeleteBackupOrchestrator); // Mock活动函数的返回值 harness.mockActivity('AutoDeleteBackUpDeterminer', () => ['backup-db-01', 'backup-db-02']); harness.mockActivity('AutoDeleteBackUpActivity', (input) => `Deleted backup: ${input}`); }); it('should call determiner activity and trigger parallel delete tasks', async () => { // 执行编排器测试 await harness.runTest('AutoDeleteBackupOrchestrator', undefined); // 验证活动调用次数 expect(harness.getState().calledActivities.length).toBe(3); // 1次判定活动 + 2次删除活动 // 验证并行删除任务是否触发 const deleteCalls = harness.getState().calledActivities.filter(a => a.name === 'AutoDeleteBackUpActivity'); expect(deleteCalls.length).toBe(2); expect(deleteCalls[0].input).toBe('backup-db-01'); expect(deleteCalls[1].input).toBe('backup-db-02'); }); });
测试定时器触发器(AutoDeleteBackupTimerTrigger)
触发器的handler是普通异步函数,只需mockcontext和Durable Client的核心方法,直接调用handler即可验证逻辑。
示例测试代码
const sinon = require('sinon'); const df = require('durable-functions'); // 导入包含触发器的模块 const triggerModule = require('./path/to/your/trigger/file'); describe('AutoDeleteBackupTimerTrigger', () => { it('should start the target orchestrator successfully', async () => { // Mock Durable Client实例 const mockClient = { startNew: sinon.stub().resolves('test-orchestration-id') }; // Mock函数上下文 const mockContext = { log: sinon.stub(), _extensionContext: { durableClient: mockClient } }; // 替换df.getClient的默认实现 const getClientStub = sinon.stub(df, 'getClient').returns(mockClient); // 调用触发器handler await triggerModule.AutoDeleteBackupTimerTrigger.handler({}, mockContext); // 验证编排器启动逻辑 expect(mockClient.startNew.calledWith('AutoDeleteBackupOrchestrator')).toBe(true); // 验证日志输出 expect(mockContext.log.calledWith('[Auto-Delete-Backup]: Started orchestration with ID: ', 'test-orchestration-id')).toBe(true); // 恢复原函数 getClientStub.restore(); }); });
测试活动函数
活动函数的handler是独立可调用的函数,直接传入测试参数即可验证输入输出逻辑:
示例测试代码
const { autoDeleteBackUpDeterminer, autoDeleteBackUpActivity } = require('../activity/autoDeleteBackUpActivity'); describe('AutoDeleteBackup Activities', () => { it('should return expected list of backups to delete', async () => { const result = await autoDeleteBackUpDeterminer(); // 根据业务逻辑断言返回值 expect(result).toEqual(expect.arrayContaining([])); // 替换为实际预期结果 }); it('should process backup deletion correctly', async () => { const testBackup = 'test-backup-db'; const result = await autoDeleteBackUpActivity(testBackup); // 断言删除逻辑执行结果 expect(result).toBeUndefined(); // 替换为实际预期返回值 }); });
内容的提问来源于stack exchange,提问作者Amarendra Patra
相关产品推荐
相关产品推荐

