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

如何在JavaScript中覆写全局函数以实现Mock?

如何Mock顶层定义的函数?

问题场景

我正在开发一个小型测试库,遇到问题:如何Mock顶层定义的函数?以下是完整单文件源码:

function main(){
  var users = getUsers();
  // ...
}

function getUsers() {
  var data = getData()
  // ... 这里假设原逻辑是返回data对应的用户列表,比如直接返回data
  return data;
}

function getData() {
  // ... get data from database
}



// test code

function mock_getData() {
  return [{id: 0, name: 'Alice'}, {id: 1, name: 'Bob'}]
}

test('getUsers', function(){
  var users = getUsers()  // 如何让getUsers中调用mock_getData而非getData?
  myAssert(users[0]['name'], 'Alice')
  myAssert(users[1]['name'], 'Bob')
})

// my very small test library
var tests = []

function myAssert(a, b) {
  if (a !== b) { throw new Error()}
}

function test(name, func) {
  tests.push({name: name, func: func})
}

function runTests() {
  for (i = 0; i < tests.length; i++) {
    var current_test = tests[i]
    try {
      current_test.func()
    } catch (err) {
      console.error(current_test.name)
    }
  }
}

解决方案

方法1:直接替换全局作用域的getData函数

你的函数都定义在全局作用域下,测试时可以直接把原getData替换成mock函数,测试完成后一定要恢复原函数,避免影响其他测试用例:

test('getUsers', function(){
  // 先保存原函数,方便后续恢复
  const originalGetData = getData;
  // 替换为mock函数
  getData = mock_getData;
  
  try {
    var users = getUsers()
    myAssert(users[0]['name'], 'Alice')
    myAssert(users[1]['name'], 'Bob')
  } finally {
    // 不管测试成功还是失败,都恢复原函数
    getData = originalGetData;
  }
})

方法2:封装到对象中(更优雅的长期方案)

如果不想依赖全局作用域的替换,可以把相关函数封装到一个模块对象里,这样Mock起来更清晰,也不会污染全局环境:

修改原业务代码:

const DataModule = {
  main(){
    var users = this.getUsers();
    // ...
  },

  getUsers() {
    var data = this.getData()
    // ... 原逻辑处理
    return data;
  },

  getData() {
    // ... 从数据库获取数据
  }
}

对应的测试代码:

test('getUsers', function(){
  const originalGetData = DataModule.getData;
  DataModule.getData = mock_getData;
  
  try {
    var users = DataModule.getUsers()
    myAssert(users[0]['name'], 'Alice')
    myAssert(users[1]['name'], 'Bob')
  } finally {
    DataModule.getData = originalGetData;
  }
})

方法3:给测试库加Mock辅助函数

可以扩展你的小型测试库,添加一个专门的Mock函数,简化重复的保存、替换、恢复操作:

// 扩展你的测试库
function mockGlobalFunc(funcName, mockFunc) {
  const original = window[funcName]; // 浏览器环境用window,Node环境换成global
  window[funcName] = mockFunc;
  // 返回一个恢复函数,调用它就能还原原函数
  return () => {
    window[funcName] = original;
  };
}

测试时使用这个辅助函数:

test('getUsers', function(){
  const restoreGetData = mockGlobalFunc('getData', mock_getData);
  
  try {
    var users = getUsers()
    myAssert(users[0]['name'], 'Alice')
    myAssert(users[1]['name'], 'Bob')
  } finally {
    restoreGetData();
  }
})

内容的提问来源于stack exchange,提问作者Wt.N

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:55:45