Trying to spy (Jasmine) on Array.prototype methods causes stack overflow

狂风中的少年 提交于 2019-12-05 08:06:42

When you spy on something jasmine creates a wrapper inorder to track the invocation of that function. Here when you spy on the prototype method basically even the push operation in jasmine itself invokes the spy instead of the actual push method on the array and it causes an infinite loop.

When you call [].push(1) it actually calls the tracker like below:

   spy = function() {
    callTracker.track({ //<-- Calls tracker to track invocation
      object: this,
      args: Array.prototype.slice.apply(arguments)
    });

which in turn calls the call tracker and pushes the call context to its internal tracker array and goes in an recursive loop till the call stack blows out.

this.track = function(context) {
  calls.push(context); //Now this again calls the spy
};

Instead if you spy on the method on array instance, you wont have this issue, since it creates a spy wrapper for the push property of that array instance (or in other words reference (currently inherited from the Array prototype) held by push of that instance gets overwritten by the new function reference of the spy created by jasmine): example:

it('does not use native push', function(){
  var arr = [];
  spyOn(arr, 'push' ).and.callThrough();
  arr.push(1);
  expect(arr.push).toHaveBeenCalledWith(1);
});

But as a real use case (at least i never had to) you could always check for the length of the target array and get the last item to compare against after a specific operation. You probably would never need to spy on native methods ( atleast not an array :) ), instead test against the object of your interest and spy on those target methods.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!