如何使用 jest 和 TypeScript 测试 express 中间件错误处理程序
How to test express middleware error handler with jest and TypeScript
我对使用 jest 测试中间件完全陌生
中间件
import HttpException from "../common/http-exception";
import { Request, Response, NextFunction } from "express";
export const errorHandler = (
error: HttpException,
request: Request,
response: Response,
next: NextFunction
) => {
const status = error.statusCode || error.status || 500;
response.status(status).send(error);
};
给出错误类型错误的失败测试:无法读取未定义的 属性 'send'
import HttpException from "../src/common/http-exception";
import { NextFunction, Request, Response, response } from "express";
import { errorHandler } from "../src/middleware/error.middleware";
describe("Error handler middleware", () => {
const error: HttpException = {
name: "error",
statusCode: 500,
status: 1,
message: "string",
error: "string"
};
let mockRequest: Partial<Request>;
let mockResponse: Partial<Response>;
let nextFunction: NextFunction = jest.fn();
beforeEach(() => {
mockRequest = {};
mockResponse = {
status: jest.fn()
};
});
test("handle error", async () => {
errorHandler(
error as HttpException,
mockRequest as Request,
mockResponse as Response,
nextFunction
);
expect(response).toBe(500);
});
});
以及 HttpException 的打字稿
export default class HttpException extends Error {
statusCode?: number;
status?: number;
message: string;
error: string | null;
constructor(statusCode: number, message: string, error?: string) {
super(message);
this.statusCode = statusCode;
this.message = message;
this.error = error || null;
}
}
在你的处理程序中,你调用 response.status(status).send(error);
,这意味着 .status()
应该 return 一个包含 send
函数的对象,但在你的模拟中 status: jest.fn()
它将 return undefined
.
对于 express 的 Response 对象,它使用链式方法,这意味着函数将 return 对象本身。
我们可以用 .mockReturnThis()
模拟相同的行为。
我也更新了您对中间件的期望:
.spec.ts
describe("Error handler middleware", () => {
const error: HttpException = {
name: "error",
statusCode: 500,
status: 1,
message: "string",
error: "string"
};
let mockRequest: Partial<Request>;
let mockResponse: Partial<Response>;
let nextFunction: NextFunction = jest.fn();
beforeEach(() => {
mockRequest = {};
mockResponse = {
status: jest.fn().mockReturnThis(), // This line
send: jest.fn(), // also mocking for send function
};
});
test("handle error when error includes statusCode", async () => {
errorHandler(
error as HttpException,
mockRequest as Request,
mockResponse as Response,
nextFunction
);
expect(mockResponse.status).toHaveBeenCalledWith(500);
expect(mockResponse.send).toHaveBeenCalledWith(error);
expect(nextFunction).not.toHaveBeenCalled();
});
});
我对使用 jest 测试中间件完全陌生
中间件
import HttpException from "../common/http-exception";
import { Request, Response, NextFunction } from "express";
export const errorHandler = (
error: HttpException,
request: Request,
response: Response,
next: NextFunction
) => {
const status = error.statusCode || error.status || 500;
response.status(status).send(error);
};
给出错误类型错误的失败测试:无法读取未定义的 属性 'send'
import HttpException from "../src/common/http-exception";
import { NextFunction, Request, Response, response } from "express";
import { errorHandler } from "../src/middleware/error.middleware";
describe("Error handler middleware", () => {
const error: HttpException = {
name: "error",
statusCode: 500,
status: 1,
message: "string",
error: "string"
};
let mockRequest: Partial<Request>;
let mockResponse: Partial<Response>;
let nextFunction: NextFunction = jest.fn();
beforeEach(() => {
mockRequest = {};
mockResponse = {
status: jest.fn()
};
});
test("handle error", async () => {
errorHandler(
error as HttpException,
mockRequest as Request,
mockResponse as Response,
nextFunction
);
expect(response).toBe(500);
});
});
以及 HttpException 的打字稿
export default class HttpException extends Error {
statusCode?: number;
status?: number;
message: string;
error: string | null;
constructor(statusCode: number, message: string, error?: string) {
super(message);
this.statusCode = statusCode;
this.message = message;
this.error = error || null;
}
}
在你的处理程序中,你调用 response.status(status).send(error);
,这意味着 .status()
应该 return 一个包含 send
函数的对象,但在你的模拟中 status: jest.fn()
它将 return undefined
.
对于 express 的 Response 对象,它使用链式方法,这意味着函数将 return 对象本身。
我们可以用 .mockReturnThis()
模拟相同的行为。
我也更新了您对中间件的期望:
.spec.ts
describe("Error handler middleware", () => {
const error: HttpException = {
name: "error",
statusCode: 500,
status: 1,
message: "string",
error: "string"
};
let mockRequest: Partial<Request>;
let mockResponse: Partial<Response>;
let nextFunction: NextFunction = jest.fn();
beforeEach(() => {
mockRequest = {};
mockResponse = {
status: jest.fn().mockReturnThis(), // This line
send: jest.fn(), // also mocking for send function
};
});
test("handle error when error includes statusCode", async () => {
errorHandler(
error as HttpException,
mockRequest as Request,
mockResponse as Response,
nextFunction
);
expect(mockResponse.status).toHaveBeenCalledWith(500);
expect(mockResponse.send).toHaveBeenCalledWith(error);
expect(nextFunction).not.toHaveBeenCalled();
});
});