TypeScript Express环境下如何用Jest Mock MongoDB查询的.exec()方法?
TypeScript Express环境下如何用Jest Mock MongoDB查询的.exec()方法?
我明白你遇到的问题了——你的测试报错是因为原函数里调用的是findOne(...).exec(),但你当前mock的findOne直接返回了Promise,而不是mongoose Query对象,自然找不到exec方法。
先给你拆解问题根源:mongoose的findOne方法本身返回的是一个Query实例,不是直接的Promise,只有调用.exec()才会触发异步查询并返回Promise。你之前的mock逻辑跳过了Query对象这一层,直接返回了mock数据的Promise,所以代码执行到.exec()时就会抛出“不是函数”的错误。
正确的Mock方式
你需要让mock的findOne返回一个带有exec方法的对象,这个exec方法再返回你预设的mock数据Promise。直接修改你的测试代码即可:
describe("getUserByUsername():", () => { test('should return a user if username matches', async () => { const mockUser: User = await userFactory.build("user"); const spy = jest.spyOn(UserModel, "findOne"); // 模拟mongoose Query对象,带exec方法 spy.mockImplementationOnce(() => ({ exec: jest.fn().mockResolvedValue(mockUser) })); const userByUsernameResult = usersHelper.getUserByUsername(mockUser.username); await expect(userByUsernameResult).resolves.toEqual(expect.objectContaining({ username: mockUser.username })); // 额外断言:确保findOne被正确调用 expect(spy).toHaveBeenCalledWith({ username: mockUser.username }); }); });
如果TypeScript类型检查报红,你可以用类型断言绕过(或者定义更严谨的Mock类型):
spy.mockImplementationOnce(() => ({ exec: jest.fn().mockResolvedValue(mockUser) }) as any);
两种测试方式的对比
你提到用MongoDB Memory Server的方式能正常工作,这两种方式各有适用场景:
- Memory Server:属于集成测试范畴,完全模拟真实数据库环境,适合验证复杂的查询逻辑、数据交互,但测试速度相对慢一点。
- Mock方式:属于单元测试范畴,只针对单个函数的逻辑,不依赖真实数据库,测试速度极快,适合快速验证函数的分支逻辑、参数传递是否正确。
备注:内容来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

