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

如何使用Jest对存在内部调用关系的两个函数进行Mock测试?

问题排查

原来的测试存在以下错误:

  • 第一个测试直接修改导入模块的componentToHex属性为mock函数无效:rgbToHex内部直接调用同模块的componentToHex,修改导出的引用不会影响模块内部的调用逻辑;同时预期调用次数1错误,rgbToHex处理r、g、b三个参数时会调用3次componentToHex
  • 第二个测试jest.spyOn使用错误:第一个参数必须是模块对象,不能传路径字符串;调用未导入的rgbToHex会报错;断言逻辑完全颠倒,rgbToHex入参是三个数字,返回值才是十六进制色值,toHaveBeenCalledWith应该匹配入参而非返回值
正确测试方案

方案1:纯功能测试(优先使用)

工具函数无需mock内部依赖,直接验证输入输出符合预期即可,这是最合理的测试方式:

import * as util from "./utils";

test("componentToHex 单数字转十六进制补零正确", () => {
  expect(util.componentToHex(15)).toBe("0f");
  expect(util.componentToHex(16)).toBe("10");
  expect(util.componentToHex(255)).toBe("ff");
});

test("rgbToHex 转换十六进制色值正确", () => {
  expect(util.rgbToHex(255, 222, 255)).toBe("#ffdeff");
  expect(util.rgbToHex(255, 255, 255)).toBe("#ffffff");
  expect(util.rgbToHex(0, 0, 0)).toBe("#000000");
});

方案2:需要验证rgbToHex调用componentToHex的逻辑

如果确实需要校验内部调用逻辑,有两种实现方式:

方式一:修改原函数调用逻辑

将原函数内部调用改为通过模块导出对象调用,即可被mock捕获:

// 工具函数修改后代码
export const componentToHex = (c) => {
  var hex = c.toString(16);
  return hex.length === 1 ? "0" + hex : hex;
};

export const rgbToHex = (r, g, b) => {
  // 改为通过导出对象调用
  return "#" + exports.componentToHex(r) + exports.componentToHex(g) + exports.componentToHex(b);
};

对应测试代码:

import * as util from "./utils";

test("rgbToHex 正确调用componentToHex 3次", () => {
  const spy = jest.spyOn(util, 'componentToHex').mockReturnValue('ff');
  const result = util.rgbToHex(255, 222, 255);
  expect(spy).toHaveBeenCalledTimes(3);
  expect(spy).toHaveBeenNthCalledWith(1, 255);
  expect(spy).toHaveBeenNthCalledWith(2, 222);
  expect(spy).toHaveBeenNthCalledWith(3, 255);
  expect(result).toBe('#ffffff');
  spy.mockRestore();
});

方式二:使用jest.mock全量mock模块

不需要修改原函数代码,直接在测试中mock整个模块即可:

// 放在测试文件最顶部,所有导入语句之前
jest.mock('./utils', () => {
  const originalModule = jest.requireActual('./utils');
  return {
    ...originalModule,
    componentToHex: jest.fn(originalModule.componentToHex)
  };
});

import * as util from "./utils";

test("rgbToHex 正确调用componentToHex 3次", () => {
  util.rgbToHex(255, 222, 255);
  expect(util.componentToHex).toHaveBeenCalledTimes(3);
  expect(util.componentToHex).toHaveBeenNthCalledWith(1, 255);
  expect(util.componentToHex).toHaveBeenNthCalledWith(2, 222);
  expect(util.componentToHex).toHaveBeenNthCalledWith(3, 255);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 16:30:05