2016-01-05 79 views
2

這是已成功解答的another question I asked的延續。

我正在學習如何使用Karma,Jasmine和ngMock對AngularJS應用程序進行單元測試。下面的代碼我有一個問題:

describe('myController function', function() { 

    describe('myController', function() { 
    var scope; 

    beforeEach(module('myApp')); 

    beforeEach(inject(function($rootScope, $controller) { 

     // These are the 2 lines I'm a bit confused about: 
     scope = $rootScope.$new(); 
     $controller('MyController', {$scope: scope}); 

    })); 

    it("..."); 
    }); 
}); 

問題1:爲什麼我們創建一個新的scope,並將其納入當地居民注射區在這一行:$controller('MyController', {$scope: scope});?它看起來工作得很好(因爲scope現在代表來自該控制器的$scope對象,並具有它應該具備的所有屬性和功能),但代碼似乎意味着我們正在用我們新創建的控制器的$scope進行重置(和空)scope(來自行scope = $rootScope.$new();)。所以我想我只是不完全瞭解這些當地人的目的/內部運作。

問題2:我也已經遠離了新scope獲取2種常見的方式創建了搜索看到,無論是路以上$rootScope.$new()顯示,或通過簡單的聲明scope = {}。即使角文檔(使用$scope = {}做到左右逢源,如here(使用$rootScope.$new())和here看到。爲什麼這樣做的一種方式比另一個?有沒有區別?

回答

2

我們爲什麼要創建一個新的範圍

有幾個原因可以想到,但簡單的答案是,如果你不想要,你不需要。你可以輕鬆地通過$rootScope,你的測試仍然可以工作。這也是典型的做法,因爲它更符合實際發生的角度 - 控制器注入的$scope特德可能是$rootScope的後代。

什麼是$控制器('MyController',{$ scope:scope});在做什麼?

ngMock模塊提供了$controller功能作爲一種構造函數用於創建你的控制器 - 很好,在技術上這是一個裝飾的ng模塊中的$controller功能,但是這並不重要。第一個參數通常是一個字符串,但可以是一個函數。

如果用函數調用,那麼它被認爲是控制器構造函數。否則它被認爲是用來檢索控制器構造函數的字符串...

第二個參數是在創建過程中注入控制器的「本地」。

因此,在您的示例中,您說您要創建「MyController」控制器,並且您想在控制器功能中將scope變量註冊爲名爲$scope的參數。

整個點,這是注入自己的scope的版本到控制器,但您在測試中創建,這樣就可以斷言發生因爲範圍的不同的東西一個版本控制器。

這是依賴注入的好處之一。

例子

如果以下是有道理的:

var scope = {}; 
scope.add = function(){}; 
expect(typeof scope.add).toBe('function'); 

然後讓我們把它一步,移動功能的加入到另一個功能:

var addFunctionToScope = function(scope) { 
    scope.add = function(){}; 
}; 
var scope = {}; 
addFunctionToScope(scope); 
expect(typeof scope.add).toBe('function'); 

現在只是假裝你的新函數將該函數添加到作用域實際上被稱爲$控制器,而不是「addFunctionToScope」。

var scope = {}; 
$controller('SomeController', {$scope: scope}); 
expect(typeof scope.add).toBe('function'); 

爲什麼要用$ rootScope。美元的新()在{}

同樣,你可以使用。但是,如果您打算使用一些示波器特定功能,如$on$new$watch等 - 您將需要注入一個實際的作用域對象,該對象使用現有作用域上的$ new函數創建。

文檔

+0

的'$ rootScope。$新的()''主場迎戰{}'是有道理的,感謝您的!我仍然不明白爲什麼我們要創建一個新的空的範圍,但它有某種方式擁有我們控制器的所有方法和屬性。我們是否實例化了一個名爲'$ scope'的屬性,並使其成爲一個空對象文字(或一個新的'$ scope'對象),然後* then *'$ contoller'用實際的Angular Controller的屬性填充它?我只是想到了可能的解釋,這對我來說是有意義的。否則我在這方面仍然有點失落。 :/ – bobbyz

+0

我想你可能會混淆範圍和控制器。範圍通常作爲一個字段注入到控制器中。然後控制器可以通過添加/刪除/更新字段來修改範圍。範圍基本上充當控制器和模板之間的粘合劑(思考視圖)。通常,您將進行測試,檢查控制器所做的每件事情。因此,如果您的控制器立即執行類似'$ scope.assigned = true;'的操作,您將在創建控制器後進行一次測試,檢查$ scope.assigned是否爲true。 –

+0

我明白範圍和控制器之間的區別,以及它如何與視圖(我認爲,至少...哈),但我感到困惑的是我們如何創建一個空的'$ scope'對象,賦值那個空白的'$ scope'對象就是我們正在測試的控制器,但是後來空白的'$ scope'對象突然擁有了來自實際控制器的所有屬性和方法。我假設我仍然在想整個過程都是錯誤的,但這就是我現在仍然堅持的地方......添加本地對象使我感到困惑:( – bobbyz