如何在NestJs中Mock aws-sdk的S3,解决仍调用真实S3的问题
NestJS S3 Mock 不生效问题解决方案
以下是该问题的常见根因及对应修复方案:
- 依赖注入Token不匹配
Nest的依赖注入体系完全通过Token匹配提供者,你注册真实S3实例用的Token必须和测试时Mock用的Token完全一致,包括字符串Token、类Token等所有类型。
示例:如果业务模块中通过自定义字符串Token注册S3:
测试时必须使用相同的Token声明Mock提供者:// 业务模块注册逻辑 @Module({ providers: [ { provide: 'AWS_S3_TOKEN', useValue: new S3({ region: process.env.AWS_REGION }) } ], exports: ['AWS_S3_TOKEN'] }) export class AwsModule {}// 测试模块注册逻辑 const testModule = await Test.createTestingModule({ providers: [ UploadService, { provide: 'AWS_S3_TOKEN', useValue: { createMultipartUpload: jest.fn().mockResolvedValue({ UploadId: 'mock-id' }), uploadPart: jest.fn().mockResolvedValue({ ETag: 'mock-etag' }), completeMultipartUpload: jest.fn().mockResolvedValue({ Location: 'mock-url' }) } } ] }).compile(); - 全局模块实例覆盖Mock
如果你的S3实例是在带@Global()装饰的全局模块中注册的,测试模块默认会加载全局模块的真实实例,优先级高于你在测试模块中声明的普通提供者。这种情况可以用overrideProvider方法强制覆盖所有注册位置的对应提供者:const testModule = await Test.createTestingModule({ imports: [UploadModule], providers: [UploadService] }) .overrideProvider('AWS_S3_TOKEN') .useValue({ /* 你的Mock实现 */ }) .compile(); - 业务代码硬编码实例化S3
如果你在业务代码中直接通过new S3()的方式创建实例,没有走Nest的依赖注入体系,Mock规则会完全失效。必须将S3实例的初始化逻辑放到模块的提供者中,通过构造函数注入的方式在业务代码中使用。 - 分片上传方法Mock不全
如果你只Mock了部分分片上传相关的S3方法,未被Mock的方法会返回undefined,如果业务代码中有异常降级逻辑,可能会触发真实S3实例的创建。确保你用到的所有S3方法都有对应的Mock实现,包括createMultipartUpload、uploadPart、completeMultipartUpload、abortMultipartUpload等。
内容的提问来源于stack exchange,提问作者Sendoff74
相关产品推荐
相关产品推荐

