Jest测试Node.js+Prisma API时roomType未定义错误排查
Jest测试Node.js+Prisma房间创建API失败排查与解决
问题现象
使用Jest测试房间创建API时出现两个问题:
- 核心报错:
TypeError: Cannot read properties of undefined (reading 'roomType') - 测试超时:
Exceeded timeout of 5000 ms for a test,且进程未正常退出
但Postman调用该API完全正常。
相关代码
服务端创建接口代码
async function createData(req, res) { const newData = req.body const data = await prisma.room.create({ data: { roomType: newData.roomType, roomImage: newData.roomImage, roomStatusId: newData.roomStatusId, roomCode: newData.roomCode, roomCapacityId: newData.roomCapacityId, category: newData.category, floor: newData.floor, i: newData.i, occupied_status: newData.occupied_status, overlook: newData.overlook, description: newData.description, bedSetup: newData.bedSetup, connecting: newData.connecting, rateCodeId: newData.rateCodeId } }); if (!data) { return errorResponse(res, 'Error', '', 404); } return successResponse( res, `Data has been inserted successfully`, data, 200, ); }
Jest测试代码
describe('POST /room', () => { it('Should create a new room', async () => { const newData = { roomType: "STANDARD", roomImage: "https://i.pravatar.cc/300", roomStatusId: 1, roomCode: 1, roomCapacityId: 1, category: "well", floor: 3, i: 2, occupied_status: true, overlook: "well", description: "kamar well", bedSetup: "well", connecting: "well", rateCodeId: 1 }; const response = await request(app) .post('/room') .send(newData); // Perform assertions expect(response.statusCode).toBe(200); expect(response.body).toHaveProperty('data'); expect(response.body.data).toMatchObject(newData); }); });
完整错误日志
FAIL __tests__/apis/room.api.test.js (9.585 s) ● POST /room › Should create a new room TypeError: Cannot read properties of undefined (reading 'roomType') 40 | const data = await prisma.room.create({ 41 | data: { > 42 | roomType: newData.roomType, | ^ 43 | roomImage: newData.roomImage, 44 | roomStatusId: newData.roomStatusId, 45 | roomCode: newData.roomCode, at roomType (src/services/room.service.js:42:31) at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5) at next (node_modules/express/lib/router/route.js:144:13) at Route.dispatch (node_modules/express/lib/router/route.js:114:3) at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5) at node_modules/express/lib/router/index.js:284:15 at Function.process_params (node_modules/express/lib/router/index.js:346:12) at next (node_modules/express/lib/router/index.js:280:10) at Function.handle (node_modules/express/lib/router/index.js:175:3) at router (node_modules/express/lib/router/index.js:47:12) at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5) at trim_prefix (node_modules/express/lib/router/index.js:328:13) at node_modules/express/lib/router/index.js:286:9 at Function.process_params (node_modules/express/lib/router/index.js:346:12) at next (node_modules/express/lib/router/index.js:280:10) at expressInit (node_modules/express/lib/middleware/init.js:40:5) at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5) at trim_prefix (node_modules/express/lib/router/index.js:328:13) at node_modules/express/lib/router/index.js:286:9 at Function.process_params (node_modules/express/lib/router/index.js:346:12) at next (node_modules/express/lib/router/index.js:280:10) at query (node_modules/express/lib/middleware/query.js:45:5) at Layer.handle [as handle_request] (node_modules/express/lib/router/layer.js:95:5) at trim_prefix (node_modules/express/lib/router/index.js:328:13) at node_modules/express/lib/router/index.js:286:9 at Function.process_params (node_modules/express/lib/router/index.js:346:12) at next (node_modules/express/lib/router/index.js:280:10) at Function.handle (node_modules/express/lib/router/index.js:175:3) at Function.handle (node_modules/express/lib/application.js:181:10) at Server.app (node_modules/express/lib/express.js:39:9) ● POST /room › Should create a new room thrown: "Exceeded timeout of 5000 ms for a test. Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout." 24 | }); 25 | describe('POST /room', () => { > 26 | it('Should create a new room', async () => { | ^ 27 | const newData = { 28 | roomType: "STANDARD", 29 | roomImage: "https://i.pravatar.cc/300", at it (__tests__/apis/room.api.test.js:26:5) at Object.describe (__tests__/apis/room.api.test.js:25:1) A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks. Active timers can also cause this, ensure that .unref() was called on them. Test Suites: 1 failed, 2 passed, 3 total Tests: 1 failed, 8 passed, 9 total Snapshots: 0 total Time: 10.968 s Ran all test suites.
问题原因
- Express未配置JSON解析中间件:服务端代码依赖
req.body获取请求数据,但Express默认不会自动解析JSON格式的请求体。Postman会自动设置Content-Type: application/json并发送正确格式数据,而测试环境中如果app实例未挂载express.json()中间件,req.body会是undefined,导致读取newData.roomType时报错。 - Prisma客户端未正确断开连接:测试结束后未关闭Prisma客户端连接,导致进程无法正常退出,触发Jest超时。
解决步骤
1. 为Express应用添加JSON解析中间件
在你的Express主入口文件中,添加以下代码(必须在挂载路由之前):
const express = require('express'); const app = express(); // 解析JSON格式的请求体 app.use(express.json()); // 挂载房间相关路由 app.use('/room', roomRouter); module.exports = app;
2. 确保测试请求发送正确格式(可选但推荐)
虽然supertest的.send()方法默认会设置Content-Type: application/json,但显式指定可以避免潜在问题:
const response = await request(app) .post('/room') .set('Content-Type', 'application/json') .send(newData);
3. 修复测试超时与资源泄漏
在测试文件末尾添加Prisma客户端的清理逻辑,确保测试完成后断开连接:
const prisma = require('../../src/prisma/client'); // 根据你的路径调整 describe('POST /room', () => { // ... 测试用例 afterAll(async () => { // 测试结束后断开Prisma连接 await prisma.$disconnect(); }); });
如果仍有超时问题,可以临时调整测试用例的超时时间:
it('Should create a new room', async () => { // ... 测试代码 }, 10000); // 设置10秒超时
4. 可选:添加请求体校验增强鲁棒性
在服务端接口中添加基础校验,防止req.body为空时崩溃:
async function createData(req, res) { const newData = req.body; // 校验必填字段 if (!newData || !newData.roomType) { return errorResponse(res, '缺少必填字段roomType', '', 400); } const data = await prisma.room.create({ data: { // ... 字段映射 } }); // ... 后续响应逻辑 }
内容的提问来源于stack exchange,提问作者Nabil Mudzaki
相关产品推荐
相关产品推荐

