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

如何让Jest与Node.js vm模块兼容以Mock系统时间?

解决Jest Mock时间在Node.js VM模块中不生效的问题

问题核心在于:Jest的useFakeTimers仅替换当前模块作用域内的Date构造函数,但vm.runInThisContext执行的代码默认会使用Node.js原生的全局Date,而非测试代码中被Mock的版本,所以始终获取真实系统时间。

下面提供两种可行的解决方法:

方法1:向VM上下文注入Mock的Date

修改业务代码,在执行VM脚本时将当前上下文的Date传入,让VM内的代码复用Jest Mock后的Date:

// myFunction.js
const vm = require('vm');
function getDateUsingVM() {
  // 构建包含当前Mock Date的上下文
  const context = { Date };
  vm.createContext(context);
  
  const script = `
    const currentDate = new Date();
    return currentDate.toISOString();
  `;
  // 使用runInContext执行脚本,绑定我们的上下文
  return vm.runInContext(script, context);
}
module.exports = getDateUsingVM;

测试代码无需修改,此时VM内的new Date()会自动使用Jest设置的Mock时间。

方法2:外部传入Date实例到VM脚本

如果允许调整业务逻辑,可以将外部创建的Date实例传入VM脚本,避免在VM内部实例化Date:

// myFunction.js
const vm = require('vm');
function getDateUsingVM(currentDate) {
  const script = `
    ((date) => date.toISOString())
  `;
  const theFunction = vm.runInThisContext(script);
  return theFunction(currentDate);
}
module.exports = getDateUsingVM;

对应的测试代码调整为:

// myFunction.test.js
const getDateUsingVM = require('./myFunction');
describe('getDateUsingVM', () => {
  beforeEach(() => {
    jest.useFakeTimers();
  });
  afterEach(() => {
    jest.useRealTimers()
  });
  test('should return the same date as the mocked date', () => {
    const mockDate = new Date('2022-01-01T12:00:00Z');
    jest.setSystemTime(mockDate);
    // 传入基于Mock时间创建的Date实例
    const result = getDateUsingVM(new Date());
    expect(result).toBe(mockDate.toISOString());
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:16:25