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

使用Jest编写消息保存POST接口测试用例时遇TypeError错误求助

解决Express+MongoDB接口Jest测试报错"TypeError: app.address is not a function"

问题概述

为基于Express+MongoDB的消息保存POST接口编写Jest测试用例时,运行测试触发以下错误:

TypeError: app.address is not a function

报错原因

你的server.js文件未导出Express的app实例,而是直接调用app.listen()启动服务器。当测试用例中require("../server")时,返回值为undefined,而supertest需要传入有效的Express app实例才能创建请求,因此触发该错误。

核心修复步骤

修改server.js导出app实例

调整server.js代码,将Express app实例导出,并仅在直接运行该文件时启动服务器:

const express = require("express");
const dotenv = require("dotenv");
const connectDB = require("./config/db");
const messageRouter = require("./routes/message.routes");
const { notFound , errorHandler} = require("./middleware/errorMiddleware");

dotenv.config();
connectDB();
const app = express();

app.use(express.json());

app.get("/", (req, res) => {
    res.send("API is Running");
});

app.use("/api/message", messageRouter);

app.use(notFound);
app.use(errorHandler);

// 导出app实例供测试使用
module.exports = app;

// 仅当直接运行server.js时启动服务器
if (require.main === module) {
  const PORT = process.env.PORT || 5000;
  app.listen(PORT, console.log(`server is running on PORT ${PORT}`));
}

测试用例的额外修正

除核心修复外,测试用例还有几个问题需要调整才能正常运行:

1. 处理认证中间件

/api/message/save接口使用了protect中间件,测试时需模拟已认证用户,可通过mock中间件实现:

// 在测试文件顶部添加
jest.mock("../middleware/authenticationMiddleware", () => ({
  protect: (req, res, next) => {
    req.user = { _id: new mongoose.Types.ObjectId() }; // 模拟用户ID
    next();
  },
}));

2. 修正数据库操作

  • 使用测试专用数据库:在.env.test中配置独立的测试MongoDB URI,避免污染生产数据
  • 清理测试数据:在afterEach中删除测试生成的消息,而非关闭数据库连接
    afterEach(async () => {
      await Message.deleteMany({}); // 清理Message集合
    });
    

3. 修正断言逻辑

测试中的expect(res.body.name).toBe("Message 1")无效,因为Message模型没有name字段,需断言存在的字段:

expect(res.statusCode).toBe(201);
expect(res.body.writerName).toBe("wN");
expect(res.body.description).toBe("Description");

4. 生成有效的ObjectId

user字段为ObjectId类型,需确保传入有效值(通过mock中间件已自动处理)。

最终修正后的测试用例示例

const mongoose = require("mongoose");
const request = require("supertest");
const app = require("../server"); // 现在能正确获取app实例
const Message = require("../models/Message.Model");

require("dotenv").config();

beforeEach(async () => {
  await mongoose.connect(process.env.MONGO_URI);
});

afterEach(async () => {
  await Message.deleteMany({});
  await mongoose.connection.close();
});

// Mock认证中间件
jest.mock("../middleware/authenticationMiddleware", () => ({
  protect: (req, res, next) => {
    req.user = { _id: new mongoose.Types.ObjectId() };
    next();
  },
}));

describe("POST /api/message/save", () => {
  it("should create a message", async () => {
    const res = await request(app).post("/api/message/save").send({
      writerName: "wN",
      date: "12",
      description: "Description",
    });

    expect(res.statusCode).toBe(201);
    expect(res.body.writerName).toBe("wN");
    expect(res.body.description).toBe("Description");
    expect(mongoose.Types.ObjectId.isValid(res.body.user)).toBe(true);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:50:41