如何用Jest Mock测试Express的healthCheck控制器?
解决Express healthCheck控制器的Mock测试问题
1. 修正基础请求/响应Mock的问题
你的mockRequest里把req.body和req.params定义成了函数,但Express中这两个本来就是对象(而非可调用方法),需要修正:
const mockRequest = () => { return { body: {}, params: {} }; };
2. Mock 核心依赖项
2.1 Mock log函数
假设log是从其他模块导入的,用Jest直接Mock整个模块:
// 测试文件顶部 jest.mock('../logger.js', () => ({ log: jest.fn() })); import { log } from '../logger.js';
2.2 Mock process.uptime
用Jest的spyOn固定返回值,避免测试结果受真实运行时间影响:
jest.spyOn(process, 'uptime').mockReturnValue(123);
2.3 Mock Date.now
同样用spyOnMock时间戳,保证测试结果可预测:
const mockTimestamp = 1620000000000; jest.spyOn(Date, 'now').mockReturnValue(mockTimestamp);
3. 完善测试用例
3.1 正常场景测试(res.send成功)
验证控制器返回正确的健康检查数据:
it('should return valid health check data', async () => { const req = mockRequest(); const res = mockResponse(); const next = mockNext(); // 固定依赖返回值 const mockUptime = 123; const mockTimestamp = 1620000000000; jest.spyOn(process, 'uptime').mockReturnValue(mockUptime); jest.spyOn(Date, 'now').mockReturnValue(mockTimestamp); await healthCheck(req, res, next); // 验证log调用 expect(log).toHaveBeenCalledWith('debug', 'healthCheck controller called'); // 验证返回数据正确性 expect(res.send).toHaveBeenCalledWith({ uptime: mockUptime, message: 'Server is running!', now_timestamp: mockTimestamp }); // 异常处理方法未触发 expect(res.status).not.toHaveBeenCalled(); });
3.2 异常场景测试(res.send抛出错误)
模拟res.send失败的情况,验证错误处理逻辑:
it('should handle res.send failure with 503 status', async () => { const req = mockRequest(); const res = mockResponse(); const next = mockNext(); // 模拟send方法抛出错误 const mockError = new Error('Send failed'); res.send.mockImplementation(() => { throw mockError; }); jest.spyOn(process, 'uptime').mockReturnValue(456); await healthCheck(req, res, next); // 验证错误处理流程 expect(res.status).toHaveBeenCalledWith(503); expect(res.send).toHaveBeenCalledTimes(1); });
完整测试文件示例
import { healthCheck } from "../healthcheck.js"; import { log } from '../logger.js'; // Mock日志模块 jest.mock('../logger.js', () => ({ log: jest.fn() })); const mockRequest = () => { return { body: {}, params: {} }; }; const mockResponse = () => { const res = {}; res.get = jest.fn().mockReturnValue(res); res.send = jest.fn().mockReturnValue(res); res.status = jest.fn().mockReturnValue(res); res.json = jest.fn().mockReturnValue(res); return res; }; const mockNext = () => jest.fn(); describe("healthcheck", () => { afterEach(() => { jest.restoreAllMocks(); }); it('should return valid health check data', async () => { const req = mockRequest(); const res = mockResponse(); const next = mockNext(); const mockUptime = 123; const mockTimestamp = 1620000000000; jest.spyOn(process, 'uptime').mockReturnValue(mockUptime); jest.spyOn(Date, 'now').mockReturnValue(mockTimestamp); await healthCheck(req, res, next); expect(log).toHaveBeenCalledWith('debug', 'healthCheck controller called'); expect(res.send).toHaveBeenCalledWith({ uptime: mockUptime, message: 'Server is running!', now_timestamp: mockTimestamp }); expect(res.status).not.toHaveBeenCalled(); }); it('should handle res.send failure with 503 status', async () => { const req = mockRequest(); const res = mockResponse(); const next = mockNext(); const mockError = new Error('Send failure'); res.send.mockImplementation(() => { throw mockError; }); jest.spyOn(process, 'uptime').mockReturnValue(456); await healthCheck(req, res, next); expect(res.status).toHaveBeenCalledWith(503); expect(res.send).toHaveBeenCalledTimes(1); }); });
内容的提问来源于stack exchange,提问作者Bruno Peixoto
相关产品推荐
相关产品推荐

