In the following code block (example #1), expect(this.req.headers["user-agent"]).to.equal("BOOM")
throws error and test fails.
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)
})
})
In the following code block (example #2), expect(requestBody.message).to.equal("BOOM")
throws "silent" error (return [200]
is never executed), but the test passes. Why?
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()
})
})
})
})
Using catch
and triggering reject
works, but why is this necessary when everything works fine in example #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()
})
})
})
})
Making assertions inside Nock reply
callbacks is not recommended.
There are a lot of layers between where that function gets executed and your test runner. Most notably, the client making the request. Usually clients don't handle non-request errors well and end up concealing or even glossing over the error.
There isn't one "correct" way to do this. By the looks of your second test, I'd recommend using a test level variable to store the body of the request. Then do the asserting in the captureMessage
callback.
Another note is that you're not correctly handing bubbling errors in the Promise of your second test. This line: return new Promise((resolve, reject) => {
doesn't use an async
keyword, which means you must call reject
manually or any bubbling error will be lost in the ethos.