Supertest+Jest无法发送JSON载荷,请求排查原因
问题原因
你手动把ProblemData序列化成JSON字符串传给send(),但Supertest的send()方法接收字符串时,不会自动设置Content-Type: application/json请求头。你的Express服务器依赖express.json()(或body-parser的json中间件)解析请求体,这个中间件默认只处理Content-Type为application/json的请求,导致服务器没法解析你发的JSON字符串,最终req.body为空,AJV校验自然抛出所有必填字段缺失的错误。
Postman能正常工作是因为它发JSON请求时会自动加Content-Type: application/json头,服务器能正确解析请求体。
解决方案
有两种修复方式:
方式1:直接传JavaScript对象给send()(推荐)
Supertest的send()支持直接接收对象,它会自动帮你序列化为JSON字符串,并设置正确的Content-Type头:
describe("Create a problem", () => { describe("Create a problem with valid data", () => { it("Should create a problem", async () => { const ProblemData = { title: "Pothole on Main Street", type: 2, description: "Large pothole on Main Street that is causing damage to vehicles", district: "Downtown", coordinates: "42.3584,-71.0598", address: "123 Main St, Boston, MA", photos: JSON.stringify(["pothole1.jpg", "pothole2.jpg"]), audio: "potholedowntown.mp4", }; await supertest(app) .post(`/problems/create`) .send(ProblemData) .expect(200) // 注意:创建成功应该返回200而非400,这里和你的预期响应匹配 .expect({ message: "Problem created.", }); }); }); });
另外提一句:你测试里写了.expect(400)但预期返回「Problem created」,这明显矛盾,记得改成对应API成功的状态码(比如200)。
方式2:手动设置Content-Type头(不推荐)
如果一定要手动传JSON字符串,得显式设置请求头:
await supertest(app) .post(`/problems/create`) .set('Content-Type', 'application/json') .send(payload) .expect(200) .expect({ message: "Problem created.", });
这种方式不如第一种简洁,优先用方式1。
额外提示
确保你的Express服务器已经配置了express.json()中间件,不然就算请求头正确,req.body还是会为空:
import express from 'express'; const app = express(); // 解析JSON格式的请求体 app.use(express.json());
内容的提问来源于stack exchange,提问作者Muhib Al Hasan
相关产品推荐
相关产品推荐

