2012-01-04 83 views
57

我想測試在我的Javascript對象構造函數中是否調用以下方法。從我在Jasmine文檔中看到的內容中,我可以窺探一個構造函數方法,並且可以在實例化一個對象後監聽方法,但我似乎無法在構造對象之前窺探一個方法。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 2012-06-03 02:00:46

+0

有一個預感,有一個合法的解決方案,在那裏。謝謝。 – BradGreens 2013-10-10 22:17:23

+0

這種方法有兩個問題。首先,它會導致內存泄漏 - 即將調用Klass的所有將來實例的called_method方法,並且隨着更多調用的進行,間諜的內存消耗將會增加。其次,更重要的是,這也可能導致多次測試,詢問克拉斯互相交流,因爲間諜已經被調用。您應該確保刪除間諜或將Klass.prototype.called_method重置爲測試用例末尾的原始方法。 – alecmce 2013-11-19 01:49:53

11

概括地說,我同意戴夫牛頓的答案在上面。但是,您應該考慮這種方法的一些邊緣情況。

徑的變化以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); 
    }); 
}); 

第二次測試將因爲在第一測試間諜設置橫跨測試邊界持續到第二個方法失敗; called_method不會增加call_count,所以this.call_count不等於1.也可以想出帶有誤報的場景 - 測試通過,不應該。因爲間諜依然存在,創建的Klass實例越多,間諜將消耗的內存堆越大,因爲間諜會將每次調用記錄到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」部分幾乎總結了所有內容;幾乎可以肯定的是,它應該在其他地方而不是在測試中得到修復。 – 2013-12-03 20:22:40

+0

這適用於最新版本的Jasmine。 – 2017-11-13 18:42:26

+0

是的,我認爲他們前一陣子關閉了這個問題。作爲原則,仍然值得避免探查原型。 – alecmce 2017-11-14 13:19:16