2012-01-19 77 views
36

如何模擬窗口對象?我正在做firefox擴展,我想使用茉莉花進行javascript測試。茉莉花模擬窗口對象

在我的javascript我有

 

function submit() { 
... 
var url = window.arguments[0]; 
... 
} 
 

很明顯,我在茉莉[0]嘲笑window.arguments因爲該對象不存在,如果不傳遞任何參數從window.openDialog

這是我的嘗試「與」

 

it("should submit to server", function() { 

     var localContext = { 
      "window": { 
       arguments: ["http://localhost"] 
      } 

     } 

     with(localContext); 
 

與嘲笑,但我仍然得到這個錯誤類型錯誤:無法讀取屬性「0」的定義,它是在測試運行WINDO像w.arguments [0]被消滅了與真正的窗口,因爲如果我這樣做

window.arguments[0]

測試中,它打印出的 「http:// localhost」 的正確。但是當涉及到submit()方法時,它顯示了window.argument未定義的錯誤。

回答

52

問題是,你只是覆蓋窗口對象的屬性。如果你能做到這一點,瀏覽器也可以做到這一點。因此,嘲笑每個人都可以訪問的全局對象的函數或屬性通常不是一個好主意,因爲當您嘗試訪問它們時,您無法確定您的更改會在那裏。

這將我帶到dependency injection。它是使代碼單元可測試的常見模式,重點在單元。這是什麼意思。當您創建新對象或訪問全局對象時,您不僅可以測試您的功能,還可以測試新創建的對象或全局對象的功能。要做到這一點,您不要在單元中創建新對象,而是將它們傳入。通常情況下,你會在構造函數中這樣做,但是在JavaScript函數中是以函數體作爲構造函數的對象,也可以將依賴關係簡單地傳遞給函數。

所以在你的情況下,函數依賴於全局窗口對象。所以不是試圖訪問全局窗口對象,而是將它作爲參數傳遞給你的函數。這樣做,這樣你可以在你的產品代碼,並與參數的簡單的JavaScript對象的窗口對象傳遞屬性約到您的測試:

function youWannaTest(w){ 
    console.log(w.arguments[0]); 
} 

在你的分機呼叫這樣的功能:

youWannaTest(window); 

在您的測試呼叫這樣的功能:

youWannaTest({arguments: ['someValue']}); 
+0

感謝您的答覆,所以我不能嘲笑這事呢? – toy 2012-01-19 12:41:33

+0

更新了我的答案,使這一點更清晰。 – 2012-01-19 21:17:35

1

我也認爲依賴注入是最乾淨的解決方案。

您的JS:

function submit(_window) { 
    _window = _window || window 
    ... 
    var url = _window.arguments[0]; 
    ... 
} 

單元測試:

it('works like a dream', function() { 
    var _window = { arguments: ['url'] } 
    expect(submit(_window)).toBeTotallyAwesome() 
}) 
0

是的,你可以嘲笑窗口對象。

你必須做的第一件事就是讓你的JS代碼一個變化:更換窗口$窗口

然後,您可以使用下面的代碼模擬窗:

var window = { 
    arguments : ['url'] 
}; 
現在在你的spec文件

:在beforeEach阻止

$controller('controllerName', {$window : window});