Jest+Supertest批量运行接口测试报Mongo E11000错误且delete测试失败
问题产生原因
- 测试用例执行顺序不符合预期:Jest默认开启测试用例并发执行,不会严格按照你编写的get→post→delete顺序执行,大概率delete用例会早于post用例运行,此时
payload.id还是你初始化的假ID6156c95c9ecf28237844489b,数据库中不存在对应记录,自然返回deletedCount为0。 - 接口异步逻辑存在缺陷:
/add接口中的todo.save()是Mongo异步操作,你没有加await等待操作完成就直接返回了todo对象,极端情况会出现接口已经返回_id,但数据还没落地到数据库,此时后续delete操作依然找不到对应数据。 - 测试环境没有做脏数据清理:每次运行测试前没有清空测试库的残留数据,如果你的Todos集合的
item字段设置了唯一索引,重复插入item: "test"就会抛出E11000 duplicate key重复键错误。
解决方案
1. 修复接口异步逻辑
先修改/add接口,确保数据写入数据库后再返回响应:
app.post("/add", async (req, res) => { const { item, status } = req.body; const todo = new Todos({ item, }); await todo.save(); // 新增await等待保存完成 res.send(todo); });
2. 调整测试逻辑,避免脏数据、保证执行顺序
重写测试用例,新增前置钩子清理测试数据,改用async/await写法保证用例执行的顺序依赖:
const request = require("supertest"); const app = require("../server"); const Todos = require("../你的Todos模型文件路径"); // 导入你的Mongo模型 describe("testing Todos API", () => { let payload = { id: "" }; let item = { item: "test" }; // 每次执行测试用例前清空Todos集合,避免脏数据 beforeEach(async () => { await Todos.deleteMany({}); }) it("get", async () => { const res = await request(app).get("/").expect(200); expect(res.body).toEqual({ name: "bob" }); expect(res.body.name).toEqual("bob"); }); it("post", async () => { const res = await request(app) .post("/add") .send(item) .expect(200); payload.id = res.body._id; expect(res.body.item).toEqual(item.item); }); it("delete", async () => { const res = await request(app) .delete("/delete") .send(payload); expect(res.body.deletedCount).toEqual(1); }); });
3. 强制测试串行执行(可选)
如果调整后仍有执行顺序问题,可以在运行Jest时添加--runInBand参数,强制所有测试用例串行执行,完全避免并发打乱顺序的问题。
内容的提问来源于stack exchange,提问作者relidon
相关产品推荐
相关产品推荐

