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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:11:17