如何在Jest中正确Mock带回调的Mongoose Model.find方法?
等等,要去掉AI味,所以语言要更像stackoverflow的回答,比如用更直接的语气,不要太生硬。比如把问题场景改成“你已经能成功Mock Mongoose的Promise风格find方法,但在Mock回调风格的调用时遇到了TypeScript类型错误”,然后直接说原因和解决方案。
再调整一下:
你已经能成功Mock Promise风格的find调用:
// 业务代码 Model.find({ 'a': 'b' }).then(value => { /* ... */ }).catch(err => { /* ... */ }); // Mock代码 Model.find = jest.fn().mockResolvedValue({ 'hi': 'its me' });
但当使用回调风格的find时:
// 业务代码 Model.find({ 'a': 'b' }, (err: any, value: IModel[]) => { if (err) { /* 错误处理 */ } // 处理返回结果 });
你尝试的Mock代码触发了TypeScript错误:Type 'void' is not assignable to type 'Query<any, any, {}, IModel>'
Model.find = jest.fn((conditions, callback) => { callback(null, { 'oi': 'its a me' }) });
问题根源
- TypeScript将你的Mock匹配到了带
projection/options参数的find重载版本,但你实际需要Mock的是仅接收filter和callback的重载。 - 核心问题:无论是否传入回调,Mongoose的
find方法始终返回QueryWithHelpers实例,而你的Mock函数没有返回值(默认是void),不符合类型定义要求。
正确Mock实现
要让Mock同时满足执行回调和返回合法Query实例的要求,代码如下:
import { QueryWithHelpers } from 'mongoose'; import { IModel } from './your-model-file'; // 引入你的模型类型 Model.find = jest.fn((conditions, callback) => { // 执行传入的回调,注意find返回的是文档数组 if (typeof callback === 'function') { callback(null, [{ oi: 'its a me' }]); } // 返回符合类型要求的空对象,用类型断言绕开TS检查 return {} as QueryWithHelpers<IModel[], IModel, {}, IModel>; });
如果需要模拟错误场景:
Model.find = jest.fn((conditions, callback) => { if (typeof callback === 'function') { callback(new Error('Mock database error'), null); } return {} as QueryWithHelpers<IModel[], IModel, {}, IModel>; });
注意事项
- 回调的第二个参数是文档数组(
IModel[]),不是单个对象,业务代码里如果是单个文档应该用findOne,这里要对应find的返回值类型。 - 如果你的业务代码还会对返回的Query做链式调用(比如
.sort()),可以在返回的对象上添加对应的Mock方法:return { sort: jest.fn().mockReturnThis(), exec: jest.fn().mockResolvedValue([{ oi: 'its a me' }]) } as QueryWithHelpers<IModel[], IModel, {}, IModel>;
内容的提问来源于stack exchange,提问作者</think_never_used_51bce0c785ca2f68081bfa7d91973934>
这样更自然,符合stackoverflow的回答风格,去掉了AI味,结构清晰,代码示例明确。现在整理成正确的Markdown格式,按照要求的规则来:
标题用#,二级标题用##,代码用```typescript,强调的话用*比如核心问题,不过这里用加粗的话是文本,因为Markdown里两个星号是加粗。
对,上面的内容里核心问题就是加粗,符合要求。然后末尾标注来源。
现在最终的回答就是这样。</think_never_used_51bce0c785ca2f68081bfa7d91973934># 如何在Jest中Mock Mongoose带回调的find方法(TypeScript)
你已经能成功Mock Promise风格的find调用:
// 业务代码 Model.find({ 'a': 'b' }).then(value => { /* ... */ }).catch(err => { /* ... */ }); // Mock代码 Model.find = jest.fn().mockResolvedValue({ 'hi': 'its me' });
但当使用回调风格的find时:
// 业务代码 Model.find({ 'a': 'b' }, (err: any, value: IModel[]) => { if (err) { /* 错误处理 */ } // 处理返回结果 });
你尝试的Mock代码触发了TypeScript错误:Type 'void' is not assignable to type 'Query<any, any, {}, IModel>'
Model.find = jest.fn((conditions, callback) => { callback(null, { 'oi': 'its a me' }) });
问题根源
- TypeScript将你的Mock匹配到了带
projection/options参数的find重载版本,但你实际需要Mock的是仅接收filter和callback的重载。 - 核心问题:无论是否传入回调,Mongoose的
find方法始终返回QueryWithHelpers实例,而你的Mock函数没有返回值(默认是void),不符合类型定义要求。
正确Mock实现
要让Mock同时满足执行回调和返回合法Query实例的要求,代码如下:
import { QueryWithHelpers } from 'mongoose'; import { IModel } from './your-model-file'; // 引入你的模型类型 Model.find = jest.fn((conditions, callback) => { // 执行传入的回调,注意find返回的是文档数组 if (typeof callback === 'function') { callback(null, [{ oi: 'its a me' }]); } // 返回符合类型要求的空对象,用类型断言绕开TS检查 return {} as QueryWithHelpers<IModel[], IModel, {}, IModel>; });
如果需要模拟错误场景:
Model.find = jest.fn((conditions, callback) => { if (typeof callback === 'function') { callback(new Error('Mock database error'), null); } return {} as QueryWithHelpers<IModel[], IModel, {}, IModel>; });
注意事项
- 回调的第二个参数是文档数组(
IModel[]),不是单个对象,业务代码里如果需要单个文档应该用findOne,要对应find的返回值类型。 - 如果业务代码还会对返回的Query做链式调用(比如
.sort()),可以在返回的对象上添加对应的Mock方法:return { sort: jest.fn().mockReturnThis(), exec: jest.fn().mockResolvedValue([{ oi: 'its a me' }]) } as QueryWithHelpers<IModel[], IModel, {}, IModel>;
内容的提问来源于stack exchange,提问作者</think_never_used_51bce0c785ca2f68081bfa7d91973934>

