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

如何使用Mocha、Sinon stub对NPM Request库进行单元测试?

问题根因

  • 你Stub的是request.get方法,但业务代码里调用的是顶层request()方法,Sinon的Stub没匹配到对应的调用,请求还是走了真实的网络逻辑,自然会抛出域名解析失败的Error: getaddrinfo ENOTFOUND报错。
  • 你的apiFunction没有返回Promise,测试代码里直接调用apiFunction.then会直接抛出异常,也没法等待异步回调执行完成。
  • 断言使用了assert.equal对比对象,该方法只会做引用相等判断,即使内容一致也会断言失败;同时Stub返回的是JSON序列化后的字符串,直接和对象对比也会不匹配。

修复后的代码示例

调整测试用例逻辑

describe(`api tests`, () => {
  it(`should return expected data`, async () => {
    // 直接stub顶层request方法,匹配业务代码的调用方式
    const requestStub = sinon.stub(request).yields(null, null, JSON.stringify({test: `stubtest`}))

    const res = await apiFunction()
    // 对比对象要使用deepEqual,先把返回的JSON字符串反序列化
    assert.deepEqual(JSON.parse(res), {test: "stubtest"})
    // 可选:验证Stub确实被正常调用
    assert.isTrue(requestStub.calledOnce)

    // 测试结束后恢复被Stub的方法,避免影响其他用例
    requestStub.restore()
  })
})

改造apiFunction返回Promise

const apiFunction = () => {  
  return new Promise((resolve, reject) => {
    request(
      {
        url: `http://url`
      },
      (err, response, body) => {
        if (err) return reject(err)
        console.log(body) // 输出 {"test":"stubtest"}
        resolve(body)
      })
  })
}

额外注意点

  • 如果业务代码里确实是用request.get发送请求,也可以保持Stubrequest.get,但要确保调用时用的是request.get()而不是顶层request()
  • 如果你不想手动处理Promise,也可以使用Sinon的resolves/rejects方法配合Promise化的请求库使用,代码会更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 08:30:01