You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jest为Node.js控制器编写单元测试遇500错误求助

单元测试返回500错误的原因及修复方案

错误原因分析

  • ContactModel.save的mock未返回Promise
    控制器中使用await dummyContact.save(),但你的mockContactSave是普通jest函数,默认返回undefined而非Promise对象,执行await时会抛出错误,直接进入catch分支返回500。
  • 测试用req对象缺少必要属性
    控制器依赖req.body.variables、parsedPhoneNumber、req.user._id等值,但测试代码未给req定义这些属性,会导致变量未定义触发报错。
  • AgentModel.findOne的mock冗余且不符合预期
    mockResolvedValue本身已返回Promise,额外用Promise.resolve包裹属于冗余写法;若mock返回值不符合控制器中agent变量的需求,会导致后续逻辑报错。
  • createCall的mock绑定错误
    控制器调用的是createCall函数,但测试中用jest.spyOn(call, 'create'),如果createCall并非call对象下的create方法,这个mock不会生效,导致实际执行时出错。

修正后的测试代码

test('should create a call successfully with valid data', async () => {
    // 模拟req对象,提供控制器所需的所有属性
    const req = {
        body: {
            variables: { prospectName: 'Test User' },
            // 根据实际逻辑补充生成parsedPhoneNumber的原始数据
        },
        user: { _id: 'user_123' }
    };

    // 模拟res对象的链式调用方法
    const res = {
        status: jest.fn().mockReturnThis(),
        json: jest.fn()
    };

    // 修正AgentModel.findOne的mock,直接返回符合需求的agent对象
    jest.spyOn(AgentModel, 'findOne').mockResolvedValue({ _id: 'valid_id', agentName: 'test' });

    // 让ContactModel.save返回Promise,满足await异步需求
    const mockContactSave = jest.fn().mockResolvedValue({ _id: 'contact_123' });
    jest.spyOn(ContactModel.prototype, 'save').mockImplementation(mockContactSave);

    // 正确mock独立的createCall函数(需替换为实际文件路径)
    jest.mock('../path/to/createCall', () => ({
        __esModule: true,
        default: jest.fn().mockResolvedValue({ _id: 'call_id' })
    }));
    const createCall = require('../path/to/createCall').default;

    await agentCall(req, res);

    expect(res.status).toHaveBeenCalledWith(201);
    expect(res.json).toHaveBeenCalledWith({ status: 'success', call_id: 'call_id' });
    expect(mockContactSave).toHaveBeenCalled();
    expect(createCall).toHaveBeenCalledWith(expect.objectContaining({
        agent: { _id: 'valid_id', agentName: 'test' },
        priority: 100
    }));
});

额外注意事项

  • 确保控制器中省略的代码(比如parsedPhoneNumber生成、agent获取逻辑)都被正确mock覆盖,避免未定义变量报错。
  • 若createCall是独立导入的函数,使用jest.mock直接mock整个模块比spyOn更可靠。
  • 测试完成后建议用mockRestore()清理mock,避免影响其他测试用例。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 19:05:22