如何在TypeScript中对AWS EventBridge事件模式进行单元测试?
实现EventBridge事件模式匹配工具
我们可以基于AWS EventBridge的官方匹配规则,实现一个递归的模式匹配逻辑,封装成工具类供单元测试调用。
核心实现代码(TypeScript)
type EventBridgeEvent = Record<string, any>; type EventPattern = Record<string, any>; /** * 递归匹配模式片段与事件片段 */ function matchPattern(patternValue: any, eventValue: any): boolean { // 模式值为数组:只要事件值匹配数组中任意一个元素 if (Array.isArray(patternValue)) { // 事件值是数组:检查是否有任意元素匹配模式数组中的任意元素 if (Array.isArray(eventValue)) { return eventValue.some(eventItem => patternValue.some(patternItem => matchPattern(patternItem, eventItem)) ); } // 事件值是单个值:检查是否匹配模式数组中的任意元素 return patternValue.some(patternItem => matchPattern(patternItem, eventValue)); } // 模式值为对象:递归匹配每个键值对 if (typeof patternValue === 'object' && patternValue !== null) { if (typeof eventValue !== 'object' || eventValue === null) { return false; } // 模式中的所有键必须在事件中存在且匹配 return Object.entries(patternValue).every(([key, patternVal]) => { const eventVal = eventValue[key]; if (eventVal === undefined) { return false; } return matchPattern(patternVal, eventVal); }); } // 基本类型:精确匹配 return patternValue === eventValue; } export class EventBridgeEmulator { /** * 验证事件是否符合指定的EventBridge模式 * @param pattern EventBridge事件模式 * @param event 待验证的EventBridge事件 * @returns 是否匹配 */ static evaluate(pattern: EventPattern, event: EventBridgeEvent): boolean { // 模式中的所有顶级键必须在事件中存在且匹配 return Object.entries(pattern).every(([key, patternVal]) => { const eventVal = event[key]; if (eventVal === undefined) { return false; } return matchPattern(patternVal, eventVal); }); } }
单元测试示例
结合你提供的测试框架,编写完整的单元测试:
import { EventBridgeEmulator } from './EventBridgeEmulator'; describe('EventPattern', () => { let eventPattern: EventPattern; let validEvent: EventBridgeEvent; let invalidEvent: EventBridgeEvent; beforeAll(() => { // 目标匹配模式 eventPattern = { "source": ["aws.access-analyzer"], "detail-type": ["Access Analyzer Finding"] }; // 符合模式的事件 validEvent = { "version": "0", "id": "22222222-dcba-4444-dcba-333333333333", "detail-type": "Access Analyzer Finding", "source": "aws.access-analyzer", "account": "123456789012", "time": "2019-11-21T01:22:33Z", "region": "us-west-2", "resources": ["arn:aws:access-analyzer:us-west-2:123456789012:analyzer/MyAnalyzer"], "detail": { "version": "1.0", "accountId": "123456789012", "region": "us-west-2", "isDeleted": false, "id": "bbbbaaaa-abcd-1111-abcd-666666666666", "status": "ACTIVE", "resourceType": "AWS::S3::Bucket", "resource": "arn:aws:s3:::my-bucket", "createdAt": "2019-11-20T04:58:50Z", "analyzedAt": "2019-11-21T01:22:22Z", "updatedAt": "2019-11-21T01:14:07Z", "principal": { "AWS": "999988887777" }, "action": ["s3:GetObject"], "condition": {}, "isPublic": false } }; // 不符合模式的事件(source错误) invalidEvent = { ...validEvent, "source": "aws.s3" }; }); it('should match a valid event', () => { expect(EventBridgeEmulator.evaluate(eventPattern, validEvent)).toBeTruthy(); }); it('should not match an invalid event', () => { expect(EventBridgeEmulator.evaluate(eventPattern, invalidEvent)).toBeFalsy(); }); // 测试嵌套对象和数组匹配 it('should match pattern with nested detail and array', () => { const nestedPattern: EventPattern = { "source": ["aws.access-analyzer"], "detail": { "resourceType": "AWS::S3::Bucket", "action": ["s3:GetObject"] } }; // 事件的action数组包含多个值,仍匹配 const eventWithMultipleActions = { ...validEvent, "detail": { ...validEvent.detail, "action": ["s3:GetObject", "s3:PutObject"] } }; expect(EventBridgeEmulator.evaluate(nestedPattern, eventWithMultipleActions)).toBeTruthy(); }); });
支持的匹配规则
这个实现覆盖了EventBridge的核心匹配逻辑:
- 顶级字段精确匹配(支持数组“或”规则)
- 嵌套对象的递归匹配
- 数组字段的包含匹配(事件数组只要有一个元素匹配模式值/数组中的任意元素)
- 基本类型(字符串、数字、布尔)的精确匹配
如果需要扩展支持通配符(如*、?)、前缀/后缀匹配等高级规则,可以在matchPattern函数中添加对应的字符串处理逻辑。
内容的提问来源于stack exchange,提问作者Asimov4
相关产品推荐
相关产品推荐

