async/await 是否以不同方式处理未捕获的拒绝错误?
Does async/await handle uncaught rejection errors differently?
在以下代码块(示例 #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")
抛出 "silent" 错误(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()
})
})
})
})
不建议在 Nock reply
回调中进行断言。
在执行该函数的位置和您的测试运行器之间有很多层。最值得注意的是,提出请求的客户。通常客户不能很好地处理非请求错误,最终会隐藏甚至掩盖错误。
没有一种 "correct" 方法可以做到这一点。从你的第二个测试来看,我建议使用测试级别变量来存储请求的主体。然后在 captureMessage
回调中进行断言。
另一个注意事项是您在第二次测试的 Promise 中没有正确处理冒泡错误。这行:return new Promise((resolve, reject) => {
没有使用 async
关键字,这意味着您必须手动调用 reject
否则任何冒泡错误都将在 ethos 中丢失。
在以下代码块(示例 #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")
抛出 "silent" 错误(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()
})
})
})
})
不建议在 Nock reply
回调中进行断言。
在执行该函数的位置和您的测试运行器之间有很多层。最值得注意的是,提出请求的客户。通常客户不能很好地处理非请求错误,最终会隐藏甚至掩盖错误。
没有一种 "correct" 方法可以做到这一点。从你的第二个测试来看,我建议使用测试级别变量来存储请求的主体。然后在 captureMessage
回调中进行断言。
另一个注意事项是您在第二次测试的 Promise 中没有正确处理冒泡错误。这行:return new Promise((resolve, reject) => {
没有使用 async
关键字,这意味着您必须手动调用 reject
否则任何冒泡错误都将在 ethos 中丢失。