如何用Jest测试Express的文件下载控制器?
Express CSV下载接口的Jest测试修复方案
问题根源
你的测试返回Number of calls: 0是因为两个核心问题:
- 未Mock必要的res方法:控制器里调用了
res.setHeader,但你定义的mockRes里没有这个方法,执行时会抛出错误并进入catch分支,导致res.send根本没被调用。 - 断言内容完全错误:你断言
send被传入了{ 'Content-Type': 'text/csv' },但实际控制器里send的参数是CSV字符串'ID\n1\n2\n3'。
修正后的测试代码
test('should successfully download the csv', async () => { const mockReq = {}; // 给mockRes补充setHeader的mock函数,确保控制器能正常执行 const mockRes = { setHeader: jest.fn(), send: jest.fn(), }; const mockNext = jest.fn(); await controller.getFile(mockReq, mockRes, mockNext); // 验证响应头设置是否符合预期 expect(mockRes.setHeader).toHaveBeenCalledTimes(2); expect(mockRes.setHeader).toHaveBeenNthCalledWith(1, 'Content-Type', 'text/csv'); expect(mockRes.setHeader).toHaveBeenNthCalledWith(2, 'Content-Disposition', 'attachment; filename=sample.csv'); // 验证send方法传入了正确的CSV内容 expect(mockRes.send).toHaveBeenCalledWith('ID\n1\n2\n3'); // 验证没有触发错误分支(next未被调用) expect(mockNext).not.toHaveBeenCalled(); });
关键修改说明
- 为
mockRes添加setHeader: jest.fn(),避免控制器执行时因找不到方法报错,保证正常走到res.send逻辑。 - 调整断言逻辑:既要验证响应头的设置正确性,也要验证
send方法的参数是预期的CSV字符串。 - 新增对
next函数的断言,确认接口未触发错误分支。
内容的提问来源于stack exchange,提问作者Jacky
相关产品推荐
相关产品推荐

