You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 07:10:30