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

Jest结合mongodb-memory-server时异步测试超时问题排查

Jest + Supertest 测试Express注册接口超时问题

我正在使用Jest和supertest测试一个Express应用,编写了以下两个测试用例:

  • 传入正确的注册数据时,应创建并返回新用户
  • 传入已注册的邮箱时,应返回409 Conflict错误

users.test.ts

import requests from "supertest";
import { MongoMemoryServer } from "mongodb-memory-server";
import mongoose from "mongoose";
import createServer from "../utils/createServer";
import User from "../models/User";
import { getRandomProfilePath } from "../utils/pathsGenerators";
const app = createServer();

let mongod: MongoMemoryServer;

beforeAll(async () => {
  mongod = await MongoMemoryServer.create();
  mongoose.connect(mongod.getUri());
});

afterAll(async () => {
  await mongoose.disconnect();
  await mongoose.connection.close();
  await mongod.stop();
});

const signUpData = {
  firstName: "john",
  lastName: "doe",
  email: "johndoe@gmail.com",
  password: "1234567890"
};

const userDataForModel = {
  ...signUpData,
  profilePath: getRandomProfilePath()
}

describe("auth", () => {
  describe("sign-up", () => {
    describe("given all correct sign-up data", () => {
      // 这个测试用例正常工作
      it("returns created user and token", async () => {
        const { body, statusCode, headers } = await requests(app)
          .post("/auth/sign-up")
          .send(signUpData);

          expect(headers["content-type"]).toMatch(/json/);
          expect(statusCode).toBe(201);
          expect(body.user).toBeDefined();
          expect(body.token).toBeDefined();
      })
    })

    describe("given user already exists", () => {
      it("returns 409", async () => {
        // 执行到这里后超时
        await User.create(userDataForModel);

        // 下面的代码似乎无法执行
        const { statusCode, body } = await requests(app)
          .post("/auth/sign-up")
          .send(signUpData)

        console.log(statusCode);
        console.log(body);

        expect(statusCode).toBe(409);
        expect(body.message).toBeDefined();
      })
    })
  })
})

问题详情

第二个测试用例在调用await User.create(userDataForModel)后总是超时,后续代码无法执行。控制台显示User.create()实际触发了一个成功的HTTP请求:

::ffff:127.0.0.1 - - [15/Apr/2023:16:15:33 +0000] "POST /auth/sign-up HTTP/1.1" 201 700

已尝试的解决方法

  • 使用await requests(app)...替代User.create(userDataForModel)
  • 使用axios
  • 改用beforeAll()和afterAll()而非beforeEach()和afterEach()
  • 从index.ts导入app,而非通过createServer()创建独立实例
  • 使用.then()替代async/await
  • 增加超时限制

createServer.ts

import express from "express";
import allRoutes from "../routes/index";
import globalMiddleware from "../middleware/globalMiddleware";
import notFound from "../middleware/notFound";
import errHandler from "../middleware/errHandler";

export default function createServer() {
  const app = express();

  app.use(globalMiddleware);
  app.use(allRoutes);
  app.use(notFound);
  app.use(errHandler);

  return app;
}

index.ts

import dotenv from "dotenv";
dotenv.config();
import "express-async-errors";
import connectDB from "./utils/connectDB";
import createServer from "./utils/createServer";
const PORT = process.env.PORT || 3000;

const app = createServer();

app.listen(PORT, async () => {
  console.log(`app running on port ${PORT}`);
  await connectDB();
  console.log("DB connected");
})

export default app;

核心需求

问题始终源于await User.create(userDataForModel),在第一个测试用例中运行它同样会超时。本质上需要找到一种在执行requests(app)前向数据库创建数据的方法,了解jest.fn()和jest.mock()但不清楚如何应用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:12:11