如何用Jest在NestJS单元测试中Mock Express Response的send方法
问题原因
- 类型强转导致的隐性报错:你使用
as Response将仅包含send方法的对象强制断言为完整的Express Response类型,如果方法执行过程中访问了mock对象上不存在的属性/方法,会直接抛出未定义错误,导致代码提前终止,res.send根本没有执行机会。 - 测试代码冗余问题:你给同步方法加了不必要的
async标识,虽然不会直接导致该错误,但可能引发其他时序断言问题;另外describe、it的描述和实际测试逻辑完全不匹配,容易误导排查方向。
正确实现方案
直接按需构造mock对象即可,不需要完整模拟整个Response实例,修正后的测试代码如下:
import { HealthController } from "./health.controller"; describe("Given I am accessing the HealthController", () => { let controller: HealthController; beforeEach(() => { controller = new HealthController(); }); describe("checkHealth", () => { it("should return healthy status as true", () => { const expectedRes = { healthy: true }; // 仅mock实际用到的方法即可 const mockReq = {}; const mockSendFn = jest.fn(); const mockRes = { send: mockSendFn }; controller.checkHealth(mockReq as any, mockRes as any); // 断言调用次数和入参 expect(mockSendFn).toHaveBeenCalledTimes(1); expect(mockSendFn).toHaveBeenCalledWith(expectedRes); }); }); });
可选优化
如果需要更规范的类型校验,不想用as any可以安装jest-mock-extended工具库,直接mock完整的Response类型:
import { mock } from 'jest-mock-extended'; import { Request, Response } from 'express'; import { HealthController } from "./health.controller"; describe("Given I am accessing the HealthController", () => { let controller: HealthController; const mockReq = mock<Request>(); const mockRes = mock<Response>(); beforeEach(() => { controller = new HealthController(); jest.clearAllMocks(); }); describe("checkHealth", () => { it("should return healthy status as true", () => { controller.checkHealth(mockReq, mockRes); expect(mockRes.send).toHaveBeenCalledTimes(1); expect(mockRes.send).toHaveBeenCalledWith({ healthy: true }); }); }); });
如果还是出现调用次数为0的问题,可以在controller.checkHealth调用前和res.send执行前分别加日志,确认方法是否被执行,以及是否在执行到res.send前就报错中断。
内容的提问来源于stack exchange,提问作者Jackie
相关产品推荐
相关产品推荐

