开玩笑等待 express 的默认错误处理程序
Jest await default error handler of express
给定以下设置:
const express = require("express");
const app = express();
app.get("/", function(req, res, next) {
// explicitly return an error
return next("my error");
});
// made this middleware for the example,
// solution should typically also work for express default error handling
app.use(function(error, req, res, next) {
if (error) {
res.status(500).send({ error });
throw new Error(error); // <- how to test this?
}
next();
});
app.listen(8080, function() {
console.log("server running on 8080");
}); //the server object listens on port 8080
测试:
const request = require("supertest");
const app = require("../../app.js");
const spy = jest.spyOn(global.console, "error").mockImplementation();
it("throws an error", async done => {
const res = await request(app).get("/");
expect(res.status).toBe(500);
expect(res.error.text).toContain("my error");
expect(spy).toHaveBeenCalled(); // nothing...
done();
});
用这个 example code 制作了一个 Codesandbox。不过不确定如何 运行 进行节点测试。
async
不应与 done
一起使用,如果无法达到 done()
,这会导致测试超时。
首先,错误处理程序不应该重新抛出错误,除非它是应该用另一个处理程序扩充的可重用路由器实例。如果它是连续的最后一个,它应该捕获其中可能发生的同步和异步错误。
问题是默认的错误处理程序是 triggered asynchronously 所以应该特别等待:
it("throws an error", async () => {
const spy = jest.spyOn(global.console, "error");
const res = await request(app).get("/");
expect(res.status).toBe(500);
expect(res.error.text).toContain("my error");
await new Promise(resolve = > setTimeout(resolve));
expect(spy).not.toHaveBeenCalled(); // it really shouldn't
});
更正确的处理方法是确保错误得到处理:
it("throws an error", async () => {
const defaultErrorHandler = jest.fn((err, req, res, next) => {});
app.use(defaultErrorHandler);
const res = await request(app).get("/");
expect(res.status).toBe(500);
expect(res.error.text).toContain("my error");
expect(defaultErrorHandler).not.toHaveBeenCalled();
});
给定以下设置:
const express = require("express");
const app = express();
app.get("/", function(req, res, next) {
// explicitly return an error
return next("my error");
});
// made this middleware for the example,
// solution should typically also work for express default error handling
app.use(function(error, req, res, next) {
if (error) {
res.status(500).send({ error });
throw new Error(error); // <- how to test this?
}
next();
});
app.listen(8080, function() {
console.log("server running on 8080");
}); //the server object listens on port 8080
测试:
const request = require("supertest");
const app = require("../../app.js");
const spy = jest.spyOn(global.console, "error").mockImplementation();
it("throws an error", async done => {
const res = await request(app).get("/");
expect(res.status).toBe(500);
expect(res.error.text).toContain("my error");
expect(spy).toHaveBeenCalled(); // nothing...
done();
});
用这个 example code 制作了一个 Codesandbox。不过不确定如何 运行 进行节点测试。
async
不应与 done
一起使用,如果无法达到 done()
,这会导致测试超时。
首先,错误处理程序不应该重新抛出错误,除非它是应该用另一个处理程序扩充的可重用路由器实例。如果它是连续的最后一个,它应该捕获其中可能发生的同步和异步错误。
问题是默认的错误处理程序是 triggered asynchronously 所以应该特别等待:
it("throws an error", async () => {
const spy = jest.spyOn(global.console, "error");
const res = await request(app).get("/");
expect(res.status).toBe(500);
expect(res.error.text).toContain("my error");
await new Promise(resolve = > setTimeout(resolve));
expect(spy).not.toHaveBeenCalled(); // it really shouldn't
});
更正确的处理方法是确保错误得到处理:
it("throws an error", async () => {
const defaultErrorHandler = jest.fn((err, req, res, next) => {});
app.use(defaultErrorHandler);
const res = await request(app).get("/");
expect(res.status).toBe(500);
expect(res.error.text).toContain("my error");
expect(defaultErrorHandler).not.toHaveBeenCalled();
});