【问题标题】:Trying to spy (Jasmine) on Array.prototype methods causes stack overflow试图在 Array.prototype 方法上监视 (Jasmine) 会导致堆栈溢出
【发布时间】:2015-06-10 23:45:18
【问题描述】:

这很奇怪。使用 testem 运行器和 jasmine2 并执行以下规范(尽管它正确地标记了没有期望):

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: Maximum call stack size exceeded. at http://localhost:7357/testem/jasmine2.js, line 980 html 报告页面达到规范,然后挂起没有显示任何实际结果。

最终我想做这样的事情:

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

提前感谢任何能够阐明这种奇怪现象的人。我不能监视原生原型方法吗?

【问题讨论】:

    标签: javascript jasmine prototype spy testem


    【解决方案1】:

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

    当您调用 [].push(1) 时,它实际上是 calls the tracker,如下所示:

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

    依次调用调用跟踪器和pushes the call context 到其内部跟踪器数组,并进入递归循环,直到调用堆栈溢出。

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

    相反,如果您监视数组实例上的方法,则不会遇到此问题,因为它为 that 数组实例的 push 属性创建了一个间谍包装器(或者换句话说,引用(当前继承来自该实例的push 持有的数组原型)被茉莉花创建的间谍的新函数引用覆盖):示例:

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

    但作为一个真实的用例(至少我从来没有这样做过),您始终可以检查目标数组的长度,并在特定操作后获取要比较的最后一项。您可能永远不需要监视本机方法(至少不是数组 :)),而是针对您感兴趣的对象进行测试并监视这些目标方法。

    【讨论】:

    • 啊,非常感谢!这很有意义。实际上,我正在尝试编写一个规范,该规范基本上可以确保尝试编码挑战的学生不会在任何对象上使用本机方法(即,在他们自己的解决方案代码中)——这是一个非常人为的案例,而不是真正的生产代码测试规范就像一个考试工具。我真的无法想象我什么时候需要监视普通程序中的本地方法。
    猜你喜欢
    • 1970-01-01
    • 2014-10-02
    • 1970-01-01
    • 2016-02-09
    • 2015-05-21
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多