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

Node.js Express TypeScript项目中间件测试报错求助

问题排查与修复方案

你的测试代码存在几个关键问题,导致运行报错,以下是具体分析和修复:

1. 测试逻辑与断言完全矛盾

测试描述写的是「当请求session中存在userUUID时,调用next且不抛出Account Not Active错误」,但你的断言却期望next被传入BadRequestError,这完全颠倒了预期结果。

2. 请求对象缺少中间件判断的关键字段

中间件的核心判断条件是req.session?.user?.isEmailVerified,但你构造的测试请求req里,session.user只有userUUID,没有isEmailVerified字段,导致中间件必然进入错误分支,和你的测试预期不符。

3. Mock函数创建错误

res = jest.fn as unknown as Response和next = jest.fn是错误的写法:jest.fn是一个工厂函数,必须通过调用jest.fn()才能生成有效的mock函数,直接赋值jest.fn只是引用了函数本身,无法跟踪调用情况。

4. 不必要的异步调用

你的中间件是同步函数,不需要用await调用,否则会触发Jest对未处理Promise的检测,导致额外错误。


修正后的测试代码

以下是覆盖两种场景的完整测试:

import { Request, Response, NextFunction } from "express";
import { BAD_REQUEST_ERROR_TYPES } from "../constants";
import { BadRequestError } from "../error-handling";
import isAccountActive from "./isAccountActive";

describe("isAccountActive Middleware", () => {
  describe("处理请求时", () => {
    test("当用户已邮箱验证(isEmailVerified为true),调用next且不传入错误", () => {
      // Arrange
      const req = {
        session: {
          user: {
            userUUID: "some-string",
            isEmailVerified: true // 补充关键字段
          },
        },
      } as unknown as Request;
      const res = {} as Response; // 不需要mock完整res,中间件未使用它的方法
      const next = jest.fn() as NextFunction; // 正确创建mock函数

      // Act
      isAccountActive(req, res, next); // 同步调用,无需await

      // Assert
      expect(next).toBeCalledTimes(1);
      expect(next).toBeCalledWith(); // 期望无参数调用next
    });

    test("当用户未邮箱验证(isEmailVerified为false或不存在),调用next并传入Account Not Active错误", () => {
      // Arrange
      const req = {
        session: {
          user: {
            userUUID: "some-string",
            isEmailVerified: false // 模拟未验证状态
          },
        },
      } as unknown as Request;
      const res = {} as Response;
      const next = jest.fn() as NextFunction;
      const expectedError = new BadRequestError(BAD_REQUEST_ERROR_TYPES.ACCOUNT_NOT_ACTIVE);

      // Act
      isAccountActive(req, res, next);

      // Assert
      expect(next).toBeCalledTimes(1);
      // 由于Error实例是引用类型,需匹配属性而非直接实例
      expect(next).toBeCalledWith(expect.objectContaining({
        name: expectedError.name,
        message: expectedError.message,
        httpStatus: expectedError.httpStatus
      }));
    });
  });
});

额外说明

  • 对于Error实例的断言,不要直接用new BadRequestError(...)作为匹配值,因为每次创建的实例都是不同的引用,Jest会判定不相等。改用expect.objectContaining匹配关键属性更可靠。
  • 如果需要更真实的Request/Response对象,可以使用node-mocks-http库,它能生成更贴近Express原生对象的mock,减少类型断言的复杂度。

内容的提问来源于stack exchange,提问作者Ange Uwase

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:31:02