2013-10-15 34 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