Подтвердить что ты не робот

Unit test шпион на $emit

Я пытаюсь шпионить за $emit из директивы, но почему-то я не могу заставить шпиона "слышать" $emit.

Это код в контроллере моих директив:

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

Это мой unit test:

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

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

4b9b3361

Ответ 1

В соответствии с документами здесь, вы правильно понимаете разницу между $emit и $broadcast. Однако я считаю, что проблема заключается в использовании $scope и $rootScope. Ваш $rootScope будет находиться на верхнем уровне иерархии областей. Я предполагаю (просто просмотрев ваши фрагменты, не имея возможности увидеть весь код), что ваш $scope в вашем контроллере является вложенным контроллером, что означает, что $scope в вашем контроллере является дочерним элементом приложения $rootScope.

Из-за этого, когда ваш unit test spys на функции $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');

Я уверен, что это должно решить вашу проблему. Сообщите мне, если это требует больше объяснений.

Ответ 2

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

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

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

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