如何用Jest和TypeScript模拟FileService的uploadToS3SingleFile方法?
解决Jest+TypeScript模拟FileService的uploadToS3SingleFile方法报错问题
问题说明
尝试用Jest和TypeScript模拟自定义FileService类中的uploadToS3SingleFile方法(该方法基于multer实现S3单文件上传),运行时出现错误:
TypeError: this.fileService.uploadS3SingleFile(...) is not a function
原FileService代码
class FileService { public uploadToS3SingleFile = (bucketName: string, formDataKey: string) => multer({ storage: multerS3({ s3: awsClientS3, bucket: bucketName, metadata: (req, file, cb) => { cb(null, { fieldName: file.fieldName }); }, key: (req, _file, cb) => { const uniqueFileName = `${Date.now()}--${req.params.name}`; req.fileName = uniqueFileName; cb(null, uniqueFileName); }, }), fileFilter: this.fileFilter, }).single(formDataKey); }
错误原因分析
- 方法名拼写错误:报错中的
uploadS3SingleFile是笔误,实际方法名是uploadToS3SingleFile - 箭头函数属性的模拟限制:
uploadToS3SingleFile是类的实例箭头函数属性,而非原型方法,Jest的jest.Mocked<T>默认只处理原型方法,直接赋值mock时需注意类型和方式 - 返回值类型错误:该方法返回的是Express中间件函数(同步函数),不是Promise,不能用
mockResolvedValueOnce
正确模拟方案
方案一:直接替换实例的箭头函数属性
import { FileService } from './path/to/file-service'; import { Request, Response, NextFunction } from 'express'; // 创建实例并转为Jest模拟类型 const fileServiceMock = new FileService() as jest.Mocked<FileService>; // 模拟uploadToS3SingleFile,返回自定义中间件 fileServiceMock.uploadToS3SingleFile = jest.fn((_bucketName: string, _formDataKey: string) => { return (req: Request, res: Response, next: NextFunction) => { // 可根据测试需求模拟业务逻辑,比如设置req.fileName req.fileName = 'mock-test-file-123'; next(); }; });
方案二:Mock整个FileService类
// 提前mock整个FileService模块 jest.mock('./path/to/file-service', () => { return { FileService: jest.fn().mockImplementation(() => ({ uploadToS3SingleFile: jest.fn((_bucketName, _formDataKey) => { return (req: Request, res: Response, next: NextFunction) => { req.fileName = 'mock-test-file-123'; next(); }; }) })) }; }); // 在测试用例中使用 import { FileService } from './path/to/file-service'; const fileServiceMock = new FileService() as jest.Mocked<FileService>;
关键注意点
- 严格匹配方法名:确保模拟的方法名和原类中的
uploadToS3SingleFile完全一致 - 箭头函数属性的处理:对于类的实例箭头函数属性,需直接在实例或mock类实现中定义该属性
- 返回值匹配类型:该方法返回Express中间件函数,需用
mockReturnValue或直接返回函数,不能使用Promise相关的mock方法
内容的提问来源于stack exchange,提问作者Serhii Zadorozhnyi
相关产品推荐
相关产品推荐

