AWS S3实例初始化移到函数外单元测试报错,如何实现单次初始化?
报错原因
将S3实例初始化移到模块全局作用域后,实例的创建时机为模块被导入时,而单元测试逻辑中,AWS环境变量配置、AWSMock对S3的 mock 操作都是在测试用例(it块)执行时才完成的,加载顺序完全颠倒:
- 测试脚本启动,先导入包含全局S3实例的业务代码模块,此时S3构造函数还未被mock,会执行真实的AWS S3初始化逻辑
- 若项目开启了AWS X-Ray链路追踪,初始化时会检查当前上下文是否存在可用的segment,测试环境默认没有对应上下文,就会抛出
failed to get the current sub/segment from the context new s3错误 - 模块导入完成后才会执行测试用例里的环境变量设置、S3 mock逻辑,此时已经错过了S3实例的初始化时机
原函数内初始化的写法没有问题,是因为每次调用s3Call时才会创建S3实例,此时测试用例的mock、环境变量配置已经全部生效,不会触发真实SDK的初始化检查。
实现S3接口单次初始化的方案
方案1:懒加载单例模式(最兼容测试场景)
将S3实例改为首次调用时才初始化,保证初始化时测试配置已经生效:
let s3Instance: AWS.S3 | null = null; function getS3Instance(): AWS.S3 { if (!s3Instance) { s3Instance = new AWS.S3(); } return s3Instance; } export function s3Call(action: string, params: any): Promise<any> { return getS3Instance()[action](params).promise(); }
该方案不需要修改现有测试逻辑,同时可以保证运行时S3实例只会被初始化一次。
方案2:调整测试初始化顺序
如果不想修改业务代码,可以把测试的环境变量配置、S3 mock操作提前到模块导入之前执行:
- Jest场景下可以在
jest.config.js中配置setupFiles字段,指定提前执行的初始化脚本,在脚本中完成环境变量设置、S3全局mock操作,保证导入业务代码前mock已经生效。
方案3:测试环境禁用X-Ray上下文检查
如果报错是X-Ray导致的,可以在测试环境设置环境变量AWS_XRAY_CONTEXT_MISSING = 'LOG_ERROR',将上下文缺失的报错改为日志输出,不阻断测试执行。
内容的提问来源于stack exchange,提问作者systemdebt
相关产品推荐
相关产品推荐

