2013-10-15 37 views
13

我試圖從指令中監視$ emit,但不知何故我無法讓間諜「聽到」$ emit。

這是代碼在我的指令控制器:

$scope.$on('send', function() { 
    console.log('called'); 
    $scope.$emit('resultSend', {'ok': true, 'data': ''}); 
}); 

這是我的單元測試:

var $rootScope, $compile, elm, element; 

beforeEach(inject(function ($injector) { 
    $rootScope = $injector.get('$rootScope'); 
    $compile = $injector.get('$compile'); 
    elm = angular.element('<test></test>'); 
    element = $compile(elm)($rootScope); 
})); 


it('should listen for the send broadcast and emit the resultSend', function() { 
    spyOn($rootScope, '$emit'); 
    $rootScope.$broadcast('send'); 
    expect($rootScope.$emit).toHaveBeenCalledWith('resultSend'); 
}); 

的輸出的console.log( '稱爲')通過噶打印出來,所以我猜測單元測試廣播事件確實有效。

這是否與$發射沒有廣播下來,但如果是這樣,如何捕捉它,如果不是,我該怎麼處理這種情況?

+4

您正在監視'$ rootScope'並調用'$ scope'上的'$ emit'。 –

回答

13

根據文檔here,您正確理解$emit$broadcast之間的差異。但是,我認爲問題在於您使用$scope$rootScope。您的$rootScope將位於您的作用域層次結構的頂層。我猜測你的控制器中的$scope是一個嵌套的控制器,這意味着你的控制器中的$scope是該應用程序的$rootScope的子版本(只是通過查看你的代碼片段而不能看到所有的代碼)。

因此,當您的單元測試針對$rootScope.$emit函數進行間諜時,它實際上並不會監視您的控制器的$scope.$emit()調用。這兩個「範圍」是不同的,而不是相同的東西。因此,您需要模擬您爲控制器提供的$scope,然後在其上執行spyOn

例如,在你的beforeEach

var ctrl, scope; 

beforeEach(function() { 
    module('<INSERT YOUR CONTROLLERS MODULE NAME HERE>'); 
    inject(function($rootScope, $controller) { 
     scope = $rootScope.$new(); 
     ctrl = $controller('<CTRL NAME HERE>', {$scope: scope}); 
    }); 
}); 

此代碼實際上將創建一個「模擬」的範圍變量,並會提供該對象到您的控制器,然後你可以做間諜和其他事情。如:

spyOn(scope, '$emit'); 
// do whatever triggers the "$emit" call 
expect(scope.$emit).toHaveBeenCalledWith('resultSend'); 

我很確定應該解決您的問題。讓我知道這是否需要更多解釋。

+0

很清楚,謝謝! – Maarten

+0

這種情況下的控制器是什麼? – 9blue

+0

嘿,謝謝你的信息,我使用茉莉花來測試Vue2,並且我做了同樣的事情,一個組件發出一個'組件'關閉,所以我想知道如何測試這些發射(可能有更好的方法,但是這樣做了) const構造函數= Vue.extend(Component); vm = new Constructor({propsData})。$安裝(); spyOn(vm,'$ emit'); //做任何觸發器「$ emit」調用 expect(vm。$ emit).toHaveBeenCalledWith('onComponentClose'); 謝謝! –

3

如果您的指令有一個控制器,您可以並應該與指令分開進行測試。這就是MVC架構的全部要點,你可以從V中單獨測試C;)

這就是說,這將是一個簡單的控制器測試規範。

另一個提示:你應該在你的beforeEach()塊(即間諜和其他)中完成所有的設置,然後在你的it()塊中做斷言。

最後:確保您設置的間諜位於您要傳遞到正在測試的控制器的範圍內。

+0

感謝您的指點,即使您的回答也是正確的,我只能標記一個;-) – Maarten

+1

只要人們獲得他們需要的信息,它並不是真正的「點」或任何其他內容。 –

+0

是真的,仍然認爲這是很有趣catch'em'all ;-) – Maarten