2013-10-15 6 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 выход ('называется') распечатывается кармой, поэтому я предполагаю, что тестовое широковещательное событие работает.

Связано ли это с $ emit, не транслирующим вниз, но вверх, и если да, то как я его поймаю, а если нет, как еще я могу справиться с этим делом?

+4

Вы следите за '$ rootScope' и вызываете' $ emit' на '$ scope'. –

ответ

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, и я сделал то же самое, компонент испускает «компонент», поэтому я хотел знать, как протестировать emit (вероятно, лучший способ, но это было сделано) const Constructor = Vue.extend (Component); vm = new Конструктор ({propsData}).$ Крепление(); spyOn (vm, '$ emit'); // делать все, что вызывает вызов «$ emit» ожидать (vm. $ Emit) .toHaveBeenCalledWith ('onComponentClose'); спасибо! –

3

Если ваша директива имеет контроллер, вы можете и должны проверить это отдельно от директивы. В этом весь смысл архитектуры MVC, вы можете протестировать C отдельно от V.;)

Тем не менее, это будет простая спецификация контроллера Jane.

Еще один совет: вы должны выполнить всю свою настройку в своем блоке beforeEach() (т. Е. Шпионы и т. Д.), А затем выполнить утверждения в своих блоках().

И наконец: убедитесь, что шпион, который вы настраиваете, находится на области, которую вы передаете в контроллер, который вы тестируете.

+0

спасибо за указатели, и хотя ваш ответ был верен, я могу только отметить один ;-) – Maarten

+1

Речь идет не о «точках» и т. Д., Пока люди получают информацию, необходимую им для продолжения. –

+0

правда, все еще думаю, что это забавно поймать тебя ;-) – Maarten