在JavaScript中重写全局函数以模拟

falq053o  于 2023-08-02  发布在  Java
关注(0)|答案(2)|浏览(94)

我正在做一个小规模的测试库,有一个问题。如何模拟在顶层定义的函数?在一个文件中查看完整的源代码。

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

function getUsers() {
  var data = getData()
  // ...
}

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()  // HOW TO CALL mock_getData instead of getData in getUsers ?
  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)
    }
  }
}

字符串

m0rkklqb

m0rkklqb1#

只使用函数表达式而不是声明。
例如,你可以在代码开头的某个地方设置一个全局var _DEBUG声明,如下所示:
第一个月
然后你会得到这样的东西:

// this is function expression so due to hoisting 
// it won't be defined/loaded until called 

var getData = function() {
   ...get data from database
}

字符串
那么在其他地方你可以简单地这样做:

//keep all your overrides nicely in one place

if(_DEBUG == true){

  //override the original function with this one, the good thing is that you keep the name exactly the same 

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

}

///_DEBUG = true //comment-uncomment this to have your test code working

ovfsdjhp

ovfsdjhp2#

假设运行时是浏览器,顶层函数位于窗口对象中。

//--- main.js
function getData(){
    return "getData";
}

//--- test.js

const originalGetData = getData;

function mock(){
    window.getData = function(){ return "mockData"}
}

function tearDown(){
    window.getData = originalGetData;
}

function log(){
    console.log(getData(), window.getData(), getData === window.getData);
}

log(); // getData getData true
mock();
log(); // mockData mockData true
tearDown(); 
log(); // getData getData true

字符串
如果函数不在顶层,可以使用相同的推理,您将需要更改给定的范围/模块。
如果你的服务是类/作用域,你也可以使用Proxy

相关问题