угловой жасмин: «неопределенный» не является объектом - трансляция в течение тайм-аута - ошибка

У меня есть такая функция:

 $scope.doIt = function( x, y )
 {
   $timeout( function ()
   {
     $rootScope.$broadcast( 'xxx',
     {
        message: xxx,
        status: xxx
     } );
   } ); 
 }

Эта функция работает нормально до сих пор. Но при написании теста у меня возникли некоторые проблемы.

describe( 'test doIt function...', function ()
      {
        var $rootScope, $timeout;

        beforeEach( inject( function ( _$rootScope_, _$timeout_ )
        {
          $rootScope = _$rootScope_;
          $timeout = _$timeout_;
          spyOn( $rootScope, '$broadcast' );
          spyOn( scope, 'doIt' ).and.callThrough();
        } ) );

        it( 'test broadcast will be called', inject( function ()
        {
          var testObj = {
            message: 'test1',
            status: 'test2'
          };

          scope.doIt( 'test1', 'test2' );

          expect( $rootScope.$broadcast ).not.toHaveBeenCalledWith( 'xxx', testObj );

          $timeout.flush();

          expect( $rootScope.$broadcast ).toHaveBeenCalledWith( 'xxx', testObj );

        } ) );
      }
    );

Это закончится следующей ошибкой:

TypeError: 'undefined' не является объектом (оценка '$rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, $location.$$state, oldState).defaultPrevented')

Почему? Что я делаю неправильно? Без $timeout в функции и тесте все работает нормально.

Заранее спасибо за вашу помощь.

:)

Редактировать: другая ожидаемая трансляция выдает эту проблему. Хм


person Andy D.    schedule 24.12.2014    source источник
comment
на какую строку указывает ошибка? тот что до промывки или после?   -  person hjl    schedule 24.12.2014
comment
Это кажется немного надуманным, поэтому я не уверен, чего вы действительно пытаетесь достичь. Я предполагаю, что вы определяете область действия где-то еще в спецификации (и $scope в тестируемом коде). Вы где-нибудь внедряете $rootScope в тестируемый код? В любом случае, это кажется далеко не идеальным способом тестирования: вместо того, чтобы шпионить за $rootScope.$broadcast, почему бы просто не прослушать трансляцию в вашей спецификации так же, как в обычном коде (т. е. $scope. $на)   -  person David Pisoni    schedule 04.03.2015


Ответы (2)


Я исправил эту проблему, вернув preventDefault

spyOn($rootScope, '$broadcast').and.returnValue({preventDefault: true})
person Awakening Byte    schedule 02.10.2015

Проблема -

Angular framework пытается вызвать функцию $broadcast и ожидает взамен объект от этой функции, который имеет свойство defaultPrevented.

Но из-за

spyOn( $rootScope, '$broadcast' );

в блоке beforeEach фактическая реализация $broadcast не может быть вызвана и, следовательно, она не возвращает объект, содержащий свойство defaultPrevented.

Решение -

Переместите оператор spyOn( $rootScope, '$broadcast' ); из блока beforeEach в блок it точно перед scope.doIt( 'test1', 'test2' );.

person Prash    schedule 14.04.2015
comment
У меня была та же проблема, и я исправил ее, установив для шпиона значение «andCallThrough()». - person Katana24; 30.07.2015
comment
@ Katana24 Вы только что сэкономили мне много времени, большое спасибо! - person SupimpaAllTheWay; 31.07.2015
comment
+1 Это решило мою проблему. Отдельный тест выдавал странные ошибки вещания. Перемещение шпиона в это исправило это. - person Jeremy; 08.04.2016