使用Jest/Supertest测试时express.Router()返回undefined的问题
问题描述
我用Node.js/Express.js开发了一个API,想用Jest和Supertest测试路由。应用本身运行正常,但执行测试时持续报错:
● Test suite failed to run TypeError: Cannot read properties of undefined (reading 'Router') 3 | import { requestAuth2 } from "../middleware/requestAuth2.js"; 4 | import { ListUsersCommandOutput } from "@aws-sdk/client-cognito-identity-provider"; > 5 | const router = express.Router(); | ^ 6 | 7 | router.get("/", requestAuth2, async function (req, res, next) { 8 | next(); at Object.<anonymous> (routes/users.ts:5:24) at Object.<anonymous> (app.ts:5:1) at Object.<anonymous> (__tests__/routes/auth.test.ts:2:1)
请问我需要mock Express和express Router吗?
相关代码
app.ts
import express, { Request, Response, Express } from "express"; import cookieParser from "cookie-parser"; import cors from "cors"; import logger from "morgan"; import usersRouter from "./routes/users.js"; import authRouter from "./routes/auth.js"; import monitoringRouter from "./routes/monitoring.js"; import bucketRouter from "./routes/buckets.js"; import dynamoDBRouter from "./routes/dynamoDB.js"; import stepFunctionsRouter from "./routes/stepFunctions.js"; import queueRouter from "./routes/queue.js"; const app: Express = express(); app.use(function (_req, res, next) { res.header("Access-Control-Allow-Origin", "true"); res.header( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept", ); res.header("Access-Control-Expose-Headers", "Set-Cookie, Cookie"); next(); }); app.use(logger("dev")); app.use( cors({ origin: true, credentials: true, }), ); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(`${process.env.ROUTE}/auth`, authRouter); app.use(`${process.env.ROUTE}/monitoring`, monitoringRouter); app.use(`${process.env.ROUTE}/users`, usersRouter); app.use(`${process.env.ROUTE}/bucket`, bucketRouter); app.use(`${process.env.ROUTE}/dynamodb`, dynamoDBRouter); app.use(`${process.env.ROUTE}/stepfunctions`, stepFunctionsRouter); app.use(`${process.env.ROUTE}/queue`, queueRouter); app.get("/", (_: Request, res: Response) => { res.redirect("/api/monitoring/status"); }); app.use(function (_: Request, res: Response) { res .status(404) .json({ message: "We couldn't find what you were looking for 😞" }); }); app.use(function (err: Error, _req: Request, res: Response) { console.error(err.stack); res.status(500).json(err); }); export default app;
auth路由代码
import express, { Request, Response } from "express"; import { createUser, } from "../controllers/AuthController.js"; const router = express.Router(); // REGISTER router.post("/register", async (req: Request, res: Response) => { console.log("Req body", req.body); // Retrieve user data const email: string = req.body.email; const password: string = req.body.password; // Create new user in Cognito pool try { console.log("Attempting user creation."); const newUser = await createUser({ email: email, password: password, }); console.log("New user", newUser); res.status(201).json(newUser); } catch (error) { console.log("Error", error.message); res.status(400).send(error); } });
测试代码
import request from 'supertest'; import app from "../../app"; import {createUser} from "../../controllers/AuthController"; jest.mock("../../middleware/requestAuth2", () => ({ requestAuth2: jest.fn(), })); jest.mock("../../controllers/AuthController", () => ({ createUser: jest.fn(), })); describe('POST /api/auth/register', () => { it("should create a user", async () => { const mockCreateUser = createUser as jest.Mock; try { mockCreateUser.mockResolvedValueOnce("user created"); await request(app) .post("/api/auth/register") .send({ email: "xxx", password: "xxx" }) .expect("Content-Type", /json/) .expect(201); } catch (error) { console.log(error); } }); });
解决方案
不需要mock Express和Router,这个错误的核心是users.ts中导入的express为undefined,导致调用express.Router()失败。按以下步骤排查修复:
检查TypeScript模块解析配置
- 确保
tsconfig.json中module设为NodeNext或ESNext,moduleResolution与之一致,保证ES模块导入正常工作。 - 路由导入的
.js后缀:如果是TypeScript项目,可尝试去掉导入路径的.js后缀(让TS自动解析),或确认编译后的文件路径匹配。
- 确保
修复Jest对ES模块的支持
- 若项目使用ES模块(
package.json中"type": "module"),Jest默认不兼容,需配置jest.config.js:export default { preset: 'ts-jest', testEnvironment: 'node', extensionsToTreatAsEsm: ['.ts'], moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', }, transform: { '^.+\\.tsx?$': ['ts-jest', { useESM: true }], }, };
该配置让Jest正确解析带
.js后缀的TS导入,同时支持ES模块语法。- 若项目使用ES模块(
确认Express依赖正常
- 执行
npm install express重新安装依赖,或删除node_modules和锁文件后重新安装,避免依赖损坏。
- 执行
检查
users.ts的Express导入- 确保
users.ts中的导入语句为默认导入:
而非命名导入(比如import express from 'express';import { express } from 'express')。
- 确保
临时简化测试依赖
- 暂时注释
app.ts中usersRouter的导入和使用,若测试正常运行,说明users.ts的导入逻辑存在问题,针对性修复即可。
- 暂时注释
总结:错误源于模块解析或Jest配置导致Express未被正确导入,而非需要mock Express本身。
内容的提问来源于stack exchange,提问作者arengit
相关产品推荐
相关产品推荐

