尝试对Array.prototype方法进行间谍监视(Jasmine)会导致堆栈溢出 [英] Trying to spy (Jasmine) on Array.prototype methods causes stack overflow

查看:55
本文介绍了尝试对Array.prototype方法进行间谍监视(Jasmine)会导致堆栈溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这很奇怪.将 testem 运行程序与 jasmine2 结合使用,并执行以下规范(尽管它正确地标记了没有期望):

This is pretty odd. Using the testem runner with jasmine2 and the following spec executes (though it correctly flags that there are no expectations):

describe('Spying on array.prototype methods', function(){
  it('should work this way', function(){
    spyOn( Array.prototype, 'push' ).and.callThrough();
    // expect(1).toBe(1);
  });
});

但是,添加一个 expect (任何 expect !),这会导致堆栈在 testem 控制台中显示以下消息: RangeError:超出了最大调用堆栈大小.在http://localhost:7357/testem/jasmine2.js,第980行 html报告页面符合规范,然后挂起而未显示任何实际结果.

However, add an expect (any expect!) and it causes the stack to overflow with the following message in the testem console: RangeError: Maximum call stack size exceeded. at http://localhost:7357/testem/jasmine2.js, line 980 The html report page gets up to the spec and then hangs without showing any actual results.

最终我想做这样的事情:

Ultimately I'd like to do something like this:

describe('Some structure.method', function(){
  it('does not use native push', function(){
    spyOn( Array.prototype, 'push' ).and.callThrough();
    [].push(1); // actually more like `myStructure.myMethod('test')`
    expect( Array.prototype.push ).not.toHaveBeenCalled();
  });
});

在此先感谢任何可以阐明这一怪异之处的人.我可以不侦察本机原型方法吗?

Thanks in advance to anyone who can shed light on this oddity. Can I not spy on native prototypical methods?

推荐答案

当您监视某些东西时,茉莉花会创建一个包装器,以跟踪该函数的调用.在这里,当您监视原型方法时,基本上甚至茉莉花本身中的push操作都会调用该间谍而不是数组上的实际push方法,并且会导致无限循环.

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.

当您调用 [].push(1)时,它实际上

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

相反,如果您监视数组实例的方法,则不会出现此问题,因为它为那个数组实例的push属性创建了一个间谍包装器(或换句话说,引用(当前继承)实例的 push 持有的Array原型中的数据被jasmine创建的间谍的新函数引用覆盖):示例:

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.

这篇关于尝试对Array.prototype方法进行间谍监视(Jasmine)会导致堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆