2015-07-12 112 views
16

我有一個函數茉莉花 - 如何spyOn實例方法

var data = {}; 
var myFunc = function() { 
    data.stuff = new ClassName().doA().doB().doC(); 
}; 

我想測試doAdoBdoC都調用。

我試圖刺探實例方法這樣

beforeEach(function() { 
    spyOn(ClassName, 'doA'); 
}; 
it('should call doA', function() { 
    myFunc(); 
    expect(ClassName.doA)toHaveBeenCalled(); 
}); 

但只是給了我一個「DOA()方法不存在」的錯誤。

任何想法?

+0

之間有一個主要區別'ClassName.doA'和'ClassName.doA()'。 – bardzusny

回答

24

您錯誤的地方在於您瞭解如何在靜態上下文中引用JavaScript中的方法。你的代碼實際上在做的是在ClassName.doA(也就是ClassName構造函數的屬性doA,這不是你想要的)附加功能。

如果您想要檢測何時在任何地方ClassName的任何實例上調用該方法,您需要監視原型。

beforeEach(function() { 
    spyOn(ClassName.prototype, 'doA'); 
}); 
it('should call doA', function() { 
    myFunc(); 
    expect(ClassName.prototype.doA).toHaveBeenCalled(); 
}); 

當然,這是假設doA住在原型鏈中。如果它是一個自己的屬性,那麼沒有能夠引用myFunc中的匿名對象的方法就沒有任何技術可用。如果您有權訪問myFunc中的ClassName實例,那麼這將是理想的,因爲您可以直接對spyOn進行操作。

P.S.你應該真的把「茉莉花」的標題。

+0

我們正面臨類似的挑戰,其中'ClassName.prototype.doA'方法會觸發,但實例字段不會在'ClassName'的實例中實例化。實例字段在構造函數中填充,但不幸的是,當我們正在監視其中一個實例方法時,它們都是未定義的。 –

+0

哇,很好的答案。我一直使用https://github.com/mfncooper/mockery模擬需要模塊緩存中的整個構造函數。它不僅更加冗長,而且有時會導致測試難以發現調試問題。這是一個很容易理解的很好的解決方案。茉莉花真的應該在他們的文檔中包含這個例子。 – Eric

5

讓我們做一些代碼重構,因爲我們希望實現構造注塑模式詹姆斯岸提到:

依賴注入意味着放棄一個對象自身的實例變量。真。而已。

var data = {}; 
var stuff = new ClassName() 

var myFunc = function(stuff) { // move step of creation new object outside 
    data.stuff = stuff.doA().doB().doC(); 
}; 

而且時間一些測試

function ClassName() { 
 
} 
 

 
var data = {}; 
 
var stuff = new ClassName() 
 

 
var myFunc = function(stuff) { 
 
    data.stuff = stuff.doA().doB().doC(); 
 
}; 
 

 

 
describe('stub for ClassName implementation', function() { 
 
    var stubStuff = { 
 
    doA: function() { 
 
     return stubStuff 
 
    }, 
 
    doB: function() { 
 
     return stubStuff 
 
    }, 
 
    doC: function() { 
 
     return stubStuff 
 
    } 
 
    } 
 

 
    beforeEach(function() { 
 
    spyOn(stubStuff, 'doA').and.callThrough(); 
 
    }); 
 

 
    it('calls "doA" on "myFunc" exection', function() { 
 
    myFunc(stubStuff); 
 
    expect(stubStuff.doA).toHaveBeenCalled(); 
 
    }); 
 
});
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" /> 
 
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>