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

Next.js+Prisma+Supertest单元测试运行失败求助

解决Next.js Edge Runtime API路由单元测试的Response不支持问题

问题背景

  • 技术栈:Next.js + TypeScript + MySQL + Prisma
  • 需求:为Edge Runtime的API GET路由编写无需启动服务器的单元测试
  • 当前错误:已在route.ts和next.config.js配置runtime: 'edge',但测试仍报错:
    API route returned a Response object in the Node.js runtime, this is not supported. Please use 'runtime: "edge"' instead
    

核心原因

你当前使用的testClient依赖的apiResolver是Node.js Runtime专属的解析器(来自next/dist/server/api-utils/node/api-resolver),无法处理Edge路由返回的NextResponse对象,必须改用Edge环境的处理逻辑。

解决方案

1. 替换测试客户端实现(testClient.ts)

直接模拟NextRequest并调用Edge路由的handler,无需依赖Node.js的http服务器:

import { NextRequest, NextResponse } from 'next/server';
import { createRequest } from 'node-mocks-http';

export const testClient = (handler: (req: NextRequest) => Promise<NextResponse>) => {
  return {
    async get(url: string) {
      // 创建模拟HTTP请求
      const mockNodeReq = createRequest({
        method: 'GET',
        url,
      });
      // 转换为Next.js Edge环境的NextRequest
      const req = new NextRequest(mockNodeReq);
      // 调用目标API handler
      const res = await handler(req);
      // 解析响应JSON内容
      const responseData = await res.json();
      // 返回便于jest断言的结构
      return {
        status: res.status,
        headers: res.headers,
        data: responseData,
        json: () => Promise.resolve(responseData),
      };
    },
    // 如需测试POST等其他方法,可扩展对应函数
  };
};

2. 调整测试用例(route.test.ts)

直接使用新的测试客户端调用handler,无需supertest:

import { GET } from "./route";
import { testClient } from "../../../../utils/test-client";

const request = testClient(GET);

describe("platform model", () => {
  it("should return 200 with success status", async () => {
    const response = await request.get("/api/platform/findMany");
    expect(response.status).toEqual(200);
    expect(response.data.success).toBe(true);
  });
});

3. 优化Jest配置(jest.config.ts)

将测试环境改为node(Edge路由基于Node.js环境,无需jsdom),同时保留polyfill:

import type {Config} from 'jest';
import nextJest from 'next/jest.js';

const createJestConfig = nextJest({
  dir: './',
})

const config: Config = {
  clearMocks: true,
  collectCoverage: true,
  coverageProvider: 'babel',
  coverageDirectory: "coverage",
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
  preset: 'ts-jest',
  setupFiles: ['./jest.polyfills.js'],
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  // 改为node环境适配Edge路由
  testEnvironment: 'node',
};

export default createJestConfig(config);

4. 保留现有polyfill(jest.polyfills.js)

无需修改,确保Response、fetch等Edge环境依赖的全局对象已被polyfill。

额外建议

  • 测试Prisma逻辑时,建议使用测试数据库(如内存数据库或临时MySQL实例),避免污染生产数据
  • 可在jest.setup.js中添加Prisma的初始化/清理逻辑:
    import { prisma } from '@/lib/db';
    
    beforeAll(async () => {
      // 可初始化测试数据
    });
    
    afterAll(async () => {
      await prisma.$disconnect();
    });
    

内容的提问来源于stack exchange,提问作者Sean Bristol-Lee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 15:47:08