You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest测试Express请求体验证中间件时出现TypeError问题求助

Express中间件Jest测试报错:Cannot read properties of undefined (reading 'json')

我写了一个验证请求体的Express中间件,代码如下:

export default function validateReqBodyMiddleware(req: Request, res: Response, next: NextFunction) {
  const { name, email }: RequestBody = req.body;
  let errors: iError[] = [];

  if (!validator.isEmail(email.trim())) errors.push({error: "invalid email", invalidField: "email"});
  if (validator.isEmpty(name.trim())) errors.push({error: "empty name", invalidField: "name"});
  
  if (errors.length) return res.status(Status.BadRequest).json(errors);
  next();
}

对应的Jest单元测试代码:

import validateRequestBody from "../../middlewares/validateRequestBody.middleware";
import { Request, Response, NextFunction } from "express";

describe("validateRequestBody middleware", () => {
  let mockRequest: Partial<Request>;
  let mockResponse: Partial<Response>;
  let nextFunction: NextFunction = jest.fn();

  beforeEach(() => {
    mockRequest = {};
    mockResponse = {
      status: jest.fn(),
      json: jest.fn(),
    };
  });

  test("wrong email format", async () => {
    const expectedResponse = [{ error: "invalid email", invalidField: "email" }];

    mockRequest = {
      body: {
        name: "John Doe",
        email: "test"
      }
    }

    validateRequestBody(
      mockRequest as Request,
      mockResponse as Response,
      nextFunction
    );

    expect(mockResponse.status).toBeCalledWith(400);
    expect(mockResponse.json).toBeCalledWith(expectedResponse);
  });
});

测试时出现如下报错:

FAIL  src/tests/unitTests/test_validateRequestBody.middleware.test.ts
  validateRequestBody middleware
    ✕ wrong email format (2 ms)

  ● validateRequestBody middleware › wrong email format

    TypeError: Cannot read properties of undefined (reading 'json')

      23 |   if (validator.isEmpty(name.trim())) errors.push({error: "empty name", invalidField: "name"});
      24 |   
    > 25 |   if (errors.length) return res.status(Status.BadRequest).json(errors);
         |                                                          ^
      26 |   next();
      27 | }

      at validateRequestBody (src/middlewares/validateRequestBody.middleware.ts:25:58)
      at Object.<anonymous> (src/tests/unitTests/test_validateRequestBody.middleware.test.ts:27:24)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.216 s, estimated 2 s
Ran all test suites.

我发现单独调用res.status()或res.json()时测试能通过,但链式调用就报错,求解决方法。


解决方案

问题根源在于你mock的status方法默认返回undefined,而Express的res.status()实际会返回响应对象本身,这样才能支持链式调用json()。

修改测试代码中mockResponse的status方法,让它返回自身:

mockResponse = {
  status: jest.fn().mockReturnThis(), // 关键修改:返回mockResponse自身
  json: jest.fn(),
};

修改后,当中间件调用res.status(400)时,会返回mockResponse对象,接着调用.json(errors)就能正常访问到json方法,测试就能通过了。

你还可以补充测试用例验证验证通过时的逻辑:

test("valid request body calls next", () => {
  mockRequest = {
    body: {
      name: "John Doe",
      email: "john@example.com"
    }
  };

  validateRequestBody(
    mockRequest as Request,
    mockResponse as Response,
    nextFunction
  );

  expect(nextFunction).toHaveBeenCalled();
  expect(mockResponse.status).not.toHaveBeenCalled();
});

内容的提问来源于stack exchange,提问作者Guilherme Massoqueto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:43:12