使用Jest模拟mongoose connection.db.collection时结果数组为空的问题
问题分析与修复方案
核心问题
jest.mock放置位置错误:jest.mock('mongoose')必须放在模块作用域(import语句之后、测试函数之外),放在测试函数内部不会生效,导致模拟逻辑无法覆盖真实的mongoose对象。- 模拟对象结构不符:MongoDB的
find()方法返回的是Cursor对象,而非直接的结果数组。你需要模拟这个Cursor对象,并让它的toArray()方法返回预期的数组Promise,而不是直接让find()返回数组Promise。
修正后的测试代码
import mongoose from 'mongoose'; // 必须放在模块作用域,确保mock在测试执行前生效 jest.mock('mongoose'); describe('mocking test suite', () => { it('should return expected array from mocked find', async () => { // 模拟MongoDB Cursor对象,实现toArray方法 const mockCursor = { toArray: jest.fn().mockResolvedValue([ { _id: mongoose.Types.ObjectId('77f6803bdd3e32292f4e4977'), data: 'something', }, { _id: mongoose.Types.ObjectId('88f6803bdd3e32292f4e4988'), data: 'another thing', }, ]) }; // 逐层模拟mongoose的嵌套结构 mongoose.connection.db.collection.mockReturnValue({ find: jest.fn().mockReturnValue(mockCursor) }); const result = await mongoose.connection.db.collection('test').find(); const arr = await result.toArray(); expect(result).toBeDefined(); expect(arr).toHaveLength(2); // 额外验证调用链,确保模拟逻辑正确触发 expect(mongoose.connection.db.collection).toHaveBeenCalledWith('test'); expect(result.toArray).toHaveBeenCalled(); }); });
补充说明
- 逐层模拟嵌套对象:mongoose的
connection.db.collection是多层嵌套结构,必须确保每一层的mock都正确返回预期对象,避免出现undefined调用方法的情况。 - 贴合真实API行为:严格按照MongoDB的实际调用逻辑模拟,
find()返回Cursor实例,toArray()才是获取最终结果的方法,这样模拟逻辑和真实代码的调用链完全匹配。
内容的提问来源于stack exchange,提问作者kpollock
相关产品推荐
相关产品推荐

