我如何测试 angularJs 事件 '$on'?

How can'I test angularJs event '$on'?

我正在使用 angularJs,我想在我的控制器中测试 $on 事件,所以我尝试以这种方式编写测试用例:

 beforeEach(inject(function ($controller,$injector) {
        $rootScope = $injector.get('$rootScope');
        $scope = $rootScope.$new();
         controller = $controller('MyController', { 
            $scope: $scope
         }); 
     }));
     spyOn($rootScope, '$broadcast').and.callThrough();
     spyOn($rootScope, '$on').and.callThrough();

      it('should set $rootScope.settings.layout.pageBodySolid to false', function() {
            controller = CreateTarget();
        expect($rootScope.$broadcast).toHaveBeenCalled();
            expect($rootScope.settings.layout.pageBodySolid).toBe(false);
        });

但是我得到这个错误:

Error: spyOn could not find an object to spy upon for $broadcast()

我也试过这样测试:

 beforeEach(inject(function ( $controller,$injector) {
        $rootScope = $injector.get('$rootScope');
        $scope = $rootScope.$new();
         controller = $controller('MyController', { 
            $scope: $scope
         });
          CreateTarget = function() {
                $controller('MyController', {$scope: $scope});
            }

     }));

 it('should set $rootScope.settings.layout.pageBodySolid to false', function() {
            controller = CreateTarget();
            $rootScope.$broadcast('$viewContent');
            expect($rootScope.settings.layout.pageBodySolid).toBe(false);
        });

这次我得到这个错误

TypeError: Cannot read property 'layout' of undefined

这是我的控制器事件

$scope.$on('$viewContent', function () {

                    $rootScope.settings.layout.pageBodySolid = false;
                    $rootScope.settings.layout.pageSidebarClosed = false;
                });

我不知道我该怎么做。这真的是我第一次体验 angularJs 测试我需要你提前 help.Thanks。

这里有几个问题:

首先是spyOn。您传递给控制器​​的 $scope 实际上是一个新实例,但您正在监视 $rootScope 对象,因此它们是两个完全不同的实例。

其次,您不一定要测试 $broadcast$on 是否被调用,因为那样您实际上是在测试 Angular。在这些情况下,您要测试的是您自己的代码和事件广播的结果。

因此,在您的情况下,您要测试的是“当收到 $viewContent 事件时,$rootScope 上的那两个属性应设置为 false。

这让我想到了第三点:layout undefined 消息是因为您试图在 $rootScopesettings 属性 上设置一个值,但是您永远不会将其初始化为任何东西。在您设置它时,它是未定义的。

TL;DR,这就是你可以测试它的方法(注意:这段代码可能需要调整。我是靠记忆输入的,而不是实际测试它是否有效。这只是为了给你一个想法)

 beforeEach(inject(function ($controller, $injector, _$rootScope_) {
        $rootScope = _$rootScope;
        $scope = $rootScope.$new();

        $rootScope.settings = {
             layout : {
                 pageBodySolid : true,
                 pageSidebarClosed : true
             }
        };

        controller = $controller('MyController', { 
            $scope: $scope
        });        
     }));

 it('should set $rootScope.settings.layout properties to false', function() {
            $rootScope.$broadcast('$viewContent');

            // Run a digest to notify watchers
            $rootScope.$digest();

            expect($rootScope.settings.layout.pageBodySolid).toBe(false);
            expect($rootScope.settings.layout.pageSidebarClosed).toBe(false);
        });