Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

With the intention to write unit tests, I want to pass an object to my function that mocks any possible property - Note: not a function property.

When I have a function like this:

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

when called someFunc({}) it will throw Cannot read property 'innerParams' of undefined'.

If there are many recursive properties in config, mocking it may be very time consuming. Is there a way to write a "mock" object that I can pass to my function to mimic any structure? It may assign undefined to all properties at the time of access, like this:

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

All I want is to avoid Cannot read property '*' of undefined' being thrown.

like image 463
Jan Grz Avatar asked Sep 17 '25 08:09

Jan Grz


2 Answers

You can use ES6 Proxy to pass access to notexisting property of object.
I would've return the object itself in that case.

But I think, it would be difficult to archive equallity to undefined.
At least I don't know the way (but I have some thoughts).

And don't forget to check Compatibility table.

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

Can't make it equal to undefined, but can to false (nonstrictly):

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;
}

Tested in FF44.

like image 84
Qwertiy Avatar answered Sep 19 '25 22:09

Qwertiy


If you have Proxy support (Firefox, IE11, and Edge for now), you can pass in

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

This is a Proxy object which allows access on properties of any name. When accessed, the value of every such property is the original proxy object itself, thereby allowing infinite chains of property access.

Property access does not yield undefined, but there is no way to do that while simultaneously allowing further property access.

like image 38
apsillers Avatar answered Sep 19 '25 21:09

apsillers