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

如何使用Jest和SuperTest Mock Express中间件类方法?

问题根源

你的verifyAuthenticated是类的箭头函数属性,这种属性在类实例化时就会被赋值给实例对象。而app.ts在启动时就导入了authMiddleware实例,并直接把verifyAuthenticated的引用绑定到了路由上。后续用jest.spyOn去mock这个属性时,路由里使用的还是最初加载的那个原函数引用,所以mock没有生效。

解决方案

方案1:将箭头函数改为原型方法

把verifyAuthenticated从箭头函数属性改成类的原型方法,这样Jest可以正确mock原型上的方法,不管实例何时创建,调用的都是原型上的方法,mock会覆盖原实现。

修改AuthMiddleware.ts:

import { Request, Response, NextFunction } from "express";

class AuthMiddleware {
  constructor() {
    console.log("AuthMiddleware instance created");
  }

  // 移除箭头,改为原型方法
  verifyAuthenticated(request: Request, response: Response, next: NextFunction) {
    console.log("This is the real deal");
    next();
  };
}

export default new AuthMiddleware();

测试代码无需修改,运行后会打印This is the mock deal,mock生效。

方案2:先Mock再导入App

如果不想修改类的方法类型,需要确保在mockverifyAuthenticated之后再导入app,避免app提前绑定原函数的引用。

修改测试文件:

import request from "supertest";
import authMiddleware from "../src/AuthMiddleware";
import { NextFunction, Request, Response } from "express";

describe("GET /", () => {
  test("Should return online.", async () => {
    // 先完成mock
    jest
      .spyOn(authMiddleware, "verifyAuthenticated")
      .mockImplementation((req: Request, res: Response, next: NextFunction) => {
        console.log("This is the mock deal");
        next();
      });

    // 延迟导入app,此时会使用mock后的方法
    const { default: app } = await import("../src/app");
    const agent = request(app);
    const response = await agent.get("/").send();

    expect(response.statusCode).toBe(200);
    expect(response.headers["content-type"]).toContain("application/json");
    expect(response.body.status).toBe("online");
  });
});

方案3:Mock整个AuthMiddleware模块

直接mock整个模块,让app导入的就是mock后的实例,从根源上替换原方法。

修改测试文件:

import request from "supertest";
import { NextFunction, Request, Response } from "express";

// 提前mock整个AuthMiddleware模块
jest.mock("../src/AuthMiddleware", () => {
  const mockVerify = (req: Request, res: Response, next: NextFunction) => {
    console.log("This is the mock deal");
    next();
  };
  return {
    default: {
      verifyAuthenticated: mockVerify
    }
  };
});

// 导入app,此时已使用mock后的模块
import app from "../src/app";

describe("GET /", () => {
  test("Should return online.", async () => {
    const agent = request(app);
    const response = await agent.get("/").send();

    expect(response.statusCode).toBe(200);
    expect(response.headers["content-type"]).toContain("application/json");
    expect(response.body.status).toBe("online");
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 18:43:16