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

如何根据参数多次Stub Mongoose的find方法并解决参数匹配错误?

问题:使用Sinon模拟Mongoose的find查询时出现参数不匹配错误

我需要模拟两个Mongoose查询:

// 查询1:统计所有用户
const totalUser = User.find().countDocuments().exec()
// 查询2:统计上周前的用户
const lastWeekUser = User.find({ createdAt: { $lt: lastWeek }}).countDocuments()

编写的Sinon Stub代码如下:

sinon
  .stub(User, 'find')
  .withArgs()
  .callsFake((): any => {
      return {
          countDocuments: sinon.stub().callsFake(() => {
              return {
                  exec: sinon.stub().returns(newUserCount),
              }
          }),
      }
  })
  .withArgs({
      createdAt: { $lt: lastWeek },
  })
  .callsFake((): any => {
      return {
          countDocuments: sinon.stub().callsFake(() => {
              return {
                  exec: sinon.stub().returns(mockedData.length),
              }
          }),
      }
  })

运行测试时出现错误:Expected 0 arguments, but got 1.


错误原因

Mongoose的find()方法如果不传任何参数,内部其实会默认传入一个空对象{},而不是完全无参数。你的第一个Stub用withArgs()严格匹配0个参数,导致实际调用User.find()时(传入了空对象)无法匹配到这个Stub,进而触发参数不匹配的错误。

另外第二个查询lastWeekUser的countDocuments()没有调用exec(),但你在Stub里还给它嵌套了exec的Stub,这也是多余的。


修正方案

1. 修正参数匹配逻辑

把无参find()的匹配从withArgs()改成withArgs({}),同时用sinon.match()处理对象参数的匹配(避免因对象引用或动态值导致匹配失败)。

2. 简化Stub结构

不需要嵌套多层callsFake,直接用returns返回对应结构即可:

sinon
  .stub(User, 'find')
  // 匹配Mongoose无参find实际传入的空对象
  .withArgs({})
  .returns({
    countDocuments: sinon.stub().returns({
      exec: sinon.stub().returns(newUserCount)
    })
  })
  // 用sinon.match.deepEqual确保深层对象匹配
  .withArgs(sinon.match.deepEqual({
    createdAt: { $lt: lastWeek }
  }))
  .returns({
    countDocuments: sinon.stub().returns(mockedData.length)
  })

补充说明

  • 如果lastWeek是动态生成的日期对象,sinon.match.deepEqual可以确保深层对象的内容匹配,而不是依赖对象引用一致。
  • Sinon完全支持对Mongoose查询的参数进行匹配,只要确保匹配逻辑和实际调用的参数一致即可。

内容的提问来源于stack exchange,提问作者Sinan Bayar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:33:32