如何用aws-sdk-client-mock编写S3上传测试?返回值为undefined的问题
问题分析与修复方案
核心问题拆解
- 测试与服务的
Upload实例不关联:你在测试代码里单独创建的Upload对象,和s3Service.uploadObject内部生成的Upload完全是两个独立实例,测试里对这个实例的操作(比如await s3Upload.done())根本不会影响服务方法的返回值。 - 断言逻辑错误:
s3Upload.on('httpUploadProgress')的返回值是Upload实例本身,不是上传完成后的结果,拿这个和服务返回值做断言本身逻辑就不成立。 - Mock不完整+Client实例不共享:你只Mock了
CreateMultipartUploadCommand和UploadPartCommand,但分片上传最后需要CompleteMultipartUploadCommand才能完成;另外如果服务内部的Upload用了新创建的S3Client,而非你传入的被Mock的实例,会导致Mock不生效,进而done()返回异常或undefined。
修复步骤
1. 确保服务使用传入的S3Client
修改S3FilesService的uploadObject方法,让内部Upload实例复用构造函数传入的客户端,避免创建新实例导致Mock失效:
class S3FilesService { constructor(s3Client, bucket) { this.s3Client = s3Client; this.bucket = bucket; } async uploadObject(key, body) { const s3Upload = new Upload({ client: this.s3Client, // 复用传入的被Mock的Client params: { Bucket: this.bucket, Key: key, Body: body, }, }); return await s3Upload.done(); // 确保这里没有遗漏return } }
2. 修正测试代码逻辑
移除测试中多余的Upload实例,专注于验证服务方法的返回值,并补全必要的Mock:
it('should upload files', async () => { const s3Mock = mockClient(S3Client); const s3 = new S3Client({}); const s3Service = new S3FilesService(s3, 'test-bucket'); // 补全分片上传全流程的Mock s3Mock.on(CreateMultipartUploadCommand).resolves({ UploadId: '1' }); s3Mock.on(UploadPartCommand).resolves({ ETag: '1' }); s3Mock.on(CompleteMultipartUploadCommand).resolves({ Location: 'https://test-bucket.s3.amazonaws.com/test', Bucket: 'test-bucket', Key: 'test', ETag: '"abc123"' }); // 调用服务上传方法 const putObjectResult = await s3Service.uploadObject( 'test', 'test' ); // 断言返回结果符合预期 expect(putObjectResult).toEqual({ Location: 'https://test-bucket.s3.amazonaws.com/test', Bucket: 'test-bucket', Key: 'test', ETag: '"abc123"' }); // 可选:验证Mock命令的调用次数,确保流程正确执行 expect(s3Mock.commandCalls(CreateMultipartUploadCommand)).toHaveLength(1); expect(s3Mock.commandCalls(UploadPartCommand)).toHaveLength(1); expect(s3Mock.commandCalls(CompleteMultipartUploadCommand)).toHaveLength(1); });
3. 排查undefined的额外检查点
如果修复后仍返回undefined,检查:
uploadObject方法是否确实返回了await s3Upload.done(),有没有漏掉return关键字;- 控制台是否有未捕获的异常,是否因为Mock不全导致
done()抛出异常但未被处理。
内容的提问来源于stack exchange,提问作者00robinette
相关产品推荐
相关产品推荐

