Jest测试失败:mockRes.status未被调用(预期200)求助排查
报错信息
expect(jest.fn()).toHaveBeenCalledWith(...expected) Expected: 200 Number of calls: 0 > 96 | expect(mockRes.status).toHaveBeenCalledWith(200);
核心问题分析
1. 未Mock removeComment服务方法,真实方法返回undefined
测试仅Mock了getArticleData和getComment,但未Mock评论服务中的removeComment方法。控制器调用真实的removeComment时,该方法因参数缺失或逻辑问题返回undefined,导致if (deletedComment)条件不成立,无法进入返回200状态码的代码分支。
2. 请求对象缺失user属性
控制器调用removeComment时依赖req.user._id,但测试构造的mockReq仅包含params,未传入user对象:
const mockReq = { params: { id: "5478ad4347dkhs", slug: 'test-article-slug' } };
这会导致req.user._id为undefined,真实的removeComment方法因参数无效返回undefined,跳过响应逻辑。
3. 未处理removeComment的异步逻辑
从其他服务方法的Promise风格推断,removeComment应为异步方法,但控制器中直接同步调用:
const deletedComment = removeComment(req.user._id, req.params.slug, req.params.id);
此时deletedComment是Promise对象而非实际结果,即使Mock后返回真值,也需要用await等待异步操作完成,否则逻辑判断可能失效。
4. Promise嵌套导致链问题
控制器混合使用then嵌套和async/await,未正确处理Promise链的返回值。若removeComment执行异常会直接进入catch(next),但核心问题还是前几点导致未进入响应分支。
修复方案
步骤1:Mock removeComment服务方法
在测试代码中添加对removeComment的Mock,让它返回真值:
const removeCommentSpy = jest.spyOn(commentHelper, "removeComment").mockResolvedValue(true);
步骤2:完善mockReq的user属性
给测试请求对象添加user属性,匹配控制器依赖:
const mockReq = { params: { id: "5478ad4347dkhs", slug: 'test-article-slug' }, user: mockUser // 引入之前定义的mockUser };
步骤3:修复控制器的异步逻辑
将控制器中的removeComment调用改为异步等待,并优化为async/await风格(更易维护):
exports.removeComment = async (req, res, next) => { try { const article = await getArticleData(req.params.slug); const comment = await getComment(req.params.id); const deletedComment = await removeComment( req.user._id, req.params.slug, req.params.id ); if (deletedComment) { return res.status(200).json({ message: 'Comment Deleted Successfully' }); } } catch (err) { next(err); } };
步骤4:补充测试断言
验证removeComment的调用是否符合预期:
expect(removeCommentSpy).toHaveBeenCalledWith(mockUser._id, mockReq.params.slug, mockReq.params.id);
内容的提问来源于stack exchange,提问作者Nilesh Sanyal

