6

これはかなり奇妙です。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(any !) を追加すると、コンソールexpectに次のメッセージが表示されてスタックがオーバーフローします。testemRangeError: Maximum call stack size exceeded. at http://localhost:7357/testem/jasmine2.js, line 980

最終的には、次のようなことをしたいと思います。

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

この奇妙なことに光を当てることができる人に前もって感謝します. ネイティブのプロトタイプ メソッドをスパイできませんか?

4

1 に答える 1

7

何かをスパイすると、ジャスミンはその関数の呼び出しを追跡するためにラッパーを作成します。ここで、基本的にプロトタイプ メソッドをスパイすると、jasmine 自体のプッシュ操作でさえ、配列の実際のプッシュ メソッドではなくスパイを呼び出し、無限ループが発生します。

呼び出す[].push(1)と、実際には以下のようにトラッカーが呼び出されます。

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

次にコール トラッカーを呼び出し、コール コンテキストを内部トラッカー配列にプッシュし、コール スタックがなくなるまで再帰ループに入ります。

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

代わりに、配列インスタンスのメソッドをスパイする場合、そのインスタンスが保持するその配列インスタンスのプッシュ プロパティ (つまり、現在は Array プロトタイプから継承されている参照)のスパイ ラッパーを作成するため、この問題は発生しませんpush。 jasmine によって作成されたスパイの新しい関数参照によって上書きされます): 例:

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

しかし、実際の使用例として (少なくとも私はする必要はありませんでした)、いつでもターゲット配列の長さをチェックし、特定の操作の後に比較する最後のアイテムを取得できます。おそらく、ネイティブメソッドをスパイする必要はまったくないでしょう(少なくとも配列ではありません:))。代わりに、関心のあるオブジェクトに対してテストし、それらのターゲットメソッドをスパイします。

于 2015-06-11T00:05:41.017 に答える