如何编写一个永远不会在 JavaScript 中抛出 "Cannot read property '**' of undefined'" 的模拟对象

How to write a mock object that will never throw "Cannot read property '**' of undefined'" in JavaScript

为了编写单元测试,我想将一个对象传递给我的函数,模拟任何可能的 属性 - 注意:不是函数 属性.

当我有这样的功能时:

function someFunc (config){
    var something = config.params.innerParams;
}

调用时 someFunc({}) 会抛出 Cannot read property 'innerParams' of undefined'.

如果config中有很多递归属性,mock可能会非常耗时。有没有办法编写一个 "mock" 对象,我可以将其传递给我的函数以模仿任何结构?它可能会在访问时为所有属性赋值undefined,像这样:

var magic = new Magic(); //magical mock created
var a1 = magic.something; //undefined;
var a2 = magic.something.innerSomething; //undefined
var a3 = magic.something.innerSomething.farAwaySomething; //undefined

我只想避免 Cannot read property '*' of undefined' 被抛出。

您可以使用 ES6 Proxy 传递对不存在 属性 对象的访问权限。
在那种情况下,我会 return 对象本身。

但我认为,undefined很难实现平等。
至少我不认识路(但我有一些想法)。

别忘了检查 Compatibility table

function Magic() {
  var res = new Proxy(this, { get(target, key, receiver) { return res } });
  return res;
}

不能使它等于未定义,但可以false(非严格):

function Magic() {
  var res = new Proxy(this, { get(target, key, receiver) { return key === Symbol.toPrimitive ? Reflect.get(target, key, receiver) : res } });
  res[Symbol.toPrimitive] = () => false;
  return res;
}

在 FF44 中测试。

如果你有 Proxy 支持(目前是 Firefox、IE11 和 Edge),你可以传入

new Proxy({}, { get(a,b,p) { return p; } })

这是一个 Proxy object,它允许访问任何名称的属性。访问时,每个这样的 属性 的值都是原始代理对象本身,从而允许 属性 访问的无限链。

属性 访问不会产生 undefined,但是没有办法同时允许进一步的 属性 访问。