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
相关产品推荐
相关产品推荐

