【问题标题】:Does async/await handle uncaught rejection errors differently?async/await 是否以不同的方式处理未捕获的拒绝错误?
【发布时间】:2020-06-24 13:53:35
【问题描述】:

在下面的代码块(示例 #1)中,expect(this.req.headers["user-agent"]).to.equal("BOOM") 抛出错误并且测试失败。

describe("http.get with headers", () => {
  it("should return response with status code 200", async () => {
    const userAgent =
      "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:74.0) Gecko/20100101 Firefox/74.0"
    nock("https://api.example.net")
      .get("/hello")
      .reply(function() {
        expect(this.req.headers["user-agent"]).to.equal("BOOM")
        return [200]
      })
    const httpInstance = new http({
      headers: {
        "user-agent": userAgent,
      },
    })
    let response = await httpInstance.get("https://api.example.net/hello")
    expect(response.statusCode).to.equal(200)
  })
})

在以下代码块(示例 #2)中,expect(requestBody.message).to.equal("BOOM") 抛出“静默”错误(return [200] 永远不会执行),但测试通过。为什么?

describe("logger.captureMessage(message, callback)", () => {
  it("should send captured exception to sentry", () => {
    return new Promise((resolve, reject) => {
      nock("https://sentry.io")
        .post("/api/3926156/store/")
        .reply((uri, requestBody: any) => {
          expect(requestBody.message).to.equal("BOOM")
          return [200]
        })
      logger.captureMessage("foo", () => {
        resolve()
      })
    })
  })
})

使用catch 并触发reject 有效,但在示例#1 中一切正常的情况下为什么需要这样做?

describe("logger.captureMessage(message, callback)", () => {
  it("should send captured exception to sentry", () => {
    return new Promise((resolve, reject) => {
      nock("https://sentry.io")
        .post("/api/3926156/store/")
        .reply((uri, requestBody: any) => {
          try {
            expect(requestBody.message).to.equal("BOOM")
            return [200]
          } catch (error) {
            reject(error)
          }
        })
      logger.captureMessage("foo", () => {
        resolve()
      })
    })
  })
})

【问题讨论】:

  • 1.你没有提供错误信息。 2. 猜测:您正在尝试访问一个不存在的属性(如 req 或 headers):this.req.headers["user-agent"]
  • @alfasin 感谢您的帮助。没有错误信息。 expect 断言根本不会抛出错误,因此即使不应该通过,测试也会通过。
  • 您的代码说:“这会引发错误并停止实验室。”所以现在我很困惑......这是没有错误消息的错误???
  • @alfasin 问题是为什么当代码非常相似时,一个期望断言会导致测试失败,而另一个不会。困惑。

标签: node.js hapijs nock lab


【解决方案1】:

不建议在 Nock reply 回调中进行断言。 在执行该函数的位置和您的测试运行程序之间有很多层。最值得注意的是,提出请求的客户。通常客户端不能很好地处理非请求错误,最终会隐藏甚至掩盖错误。

没有一种“正确”的方法可以做到这一点。从您的第二个测试来看,我建议使用测试级别变量来存储请求的正文。然后在captureMessage 回调中进行断言。

另一个注意事项是,您在第二次测试的 Promise 中没有正确处理冒泡错误。这一行:return new Promise((resolve, reject) => { 没有使用async 关键字,这意味着您必须手动调用reject,否则任何冒泡错误都将丢失。

【讨论】:

  • 感谢您帮助马特。你知道我可以在哪里阅读更多关于“另一张纸条”的信息吗?你的意思是使用asyncawait 以某种方式处理这些冒泡错误?如果是这样,为什么?如何?我注意到将expect(requestBody.level).to.equal("BOOM") 包裹在try catch 中并从catch 中调用reject 是有效的,但我不知道为什么。
  • 顺便说一句,将requestBody 存储在captureMessage 的回调内部进行分析仍然不会引发错误,但由于未执行resolve(),因此测试会因超时错误而失败。
  • 我相当有信心我的“另一条笔记”是对您发布的问题的实际答案。但是reply 中的断言是得到很多人的陷阱。至于 async/await 如何处理错误,我手头没有很好的教学资源,所以我建议四处搜索。要点是 async/await 是手动 Promises 带有错误处理的语法糖。手动构造 Promises 时,还需要手动处理错误。
猜你喜欢
  • 1970-01-01
  • 2017-12-15
  • 1970-01-01
  • 2018-09-14
  • 2020-04-07
  • 2015-06-23
  • 2018-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多