2012-01-04 12 views
57

Javascriptオブジェクトコンストラクタで次のメソッドが呼び出されているかどうかをテストします。ジャスミンの文書で見たことから、私はコンストラクタメソッドを偵察することができ、オブジェクトがインスタンス化された後にメソッドを偵察することはできますが、オブジェクトが構築される前にメソッドを偵察することはできません。私はスペックでこのような何かをしたいJasmine - コンストラクタ内でのメソッド呼び出しの盗聴

Klass = function() { 
    this.called_method(); 
}; 

Klass.prototype.called_method = function() { 
    //method to be called in the constructor. 
} 

オブジェクトに

it('should spy on a method call within the constructor', function() { 
    spyOn(window, 'Klass'); 
    var obj = new Klass(); 
    expect(window.Klass.called_method).toHaveBeenCalled(); 
}); 

答えて

98

スパイ直接プロトタイプ法上:大まか

describe("The Klass constructor", function() { 
    it("should call its prototype's called_method", function() { 
     spyOn(Klass.prototype, 'called_method'); //.andCallThrough(); 
     var k = new Klass(); 
     expect(Klass.prototype.called_method).toHaveBeenCalled(); 
    }); 
}); 
+3

ありがとうございます。最高の説明私は一日中、この件について見てきました – Subimage

+0

これに正当な解決策がありました。ありがとうございました。 – BradGreens

+0

このアプローチには2つの問題があります。まず、メモリリークを引き起こします。called_methodメソッドでは、Klassのすべてのインスタンスがスパイされ、より多くの呼び出しが行われると、スパイのメモリ消費量が増加します。第二に、さらに、これは潜在的に、スパイが既に呼び出されているため、Klassに相互作用するように質問する複数のテストを潜在的に引き起こします。テストケースの最後に、スパイが削除されているか、Klass.prototype.called_methodが元のメソッドにリセットされていることを確認する必要があります。 – alecmce

11

、私は同意します上記のDave Newtonの答え。しかし、このアプローチにはいくつか注意すべき点があります。

別のテスト・ケースで、Daveのソリューションにバリエーションを取る:

// production code 
var Klass = function() { 
    this.call_count = 0; 
    this.called_method(); 
}; 
Klass.prototype.called_method = function() { 
    ++this.call_count; 
}; 

// test code 
describe("The Klass constructor", function() { 
    it("should call its prototype's called_method", function() { 
    spyOn(Klass.prototype, 'called_method'); 
    var k = new Klass(); 
    expect(k.called_method).toHaveBeenCalled(); 
    }); 
    it('some other test', function() { 
    var k = new Klass(); 
    expect(k.call_count).toEqual(1); 
    }); 
}); 

最初のテストでスパイセットアップが第二の方法にテストの境界を越えて持続するため、2番目のテストは失敗します。 called_methodはcall_countをインクリメントしないので、this.call_countは1に等しくありません。偽陽性のシナリオを考え出すこともできます。

スパイが残っているため、スパースがcalled_methodの各呼び出しを記録するため、作成されるクラスインスタンスが多いほど、スパイが消費するメモリヒープが大きくなります。ほとんどの場合、これはおそらく問題ではありませんが、場合によってはそれに注意する必要があります。

この問題の簡単な解決策は、スパイが使用された後でスパイが削除されていることを確認することです。よりよい解決策あなたがテストするコードを容易にするために、生産コードを書く方法を変更することです - [終了する少し意見注]

// test code 
describe("The Klass constructor", function() { 
    it("should call its prototype's called_method", function() { 
    var spy = jasmine.createSpy('called_method'); 
    var method = Klass.prototype.called_method; 
    Klass.prototype.called_method = spy; 
    var k = new Klass(); 
    expect(spy).toHaveBeenCalled(); 
    Klass.prototype.called_method = method; 
    }); 

:それは少し醜い見ることができますが、このようなものは動作します。原則として、試作品を盗んでいるのは避けたいコード臭です。コンストラクタで依存関係をインスタンス化する代わりに、それらを挿入します。コンストラクタで初期化を行うのではなく、適切なinitメソッドを延期してください。

+1

+1、お寄せいただきありがとうございます。私は、下の "NOTE"セクションはすべてをすべて要約していると思います。テストではなく他の場所に修正する必要があることはほぼ確実です。 –

+0

これはJasmineの最新バージョンで動作します。 –

+0

ええ、私は彼らがこのちかを少し前に閉鎖したと思います。プロトタイプを原則として盗んだりするのをやめる価値はまだあります。 – alecmce

関連する問題