AngularJs 单元测试失败,因为 Karma 无法识别控制器中的 $scope.$on 侦听器

AngularJs unit test fails because Karma doesn't recognize $scope.$on listeners in the controller

事情是这样的。我一直在调查许多线程,但找不到与我的错误相关的任何内容。我正在尝试测试我的 angular 应用程序,(我想先澄清一下,我是 unitTesting 的新手)

根据 this tutorial 的说法,我已经设置好所有内容并且基本测试工作正常。但是当我包含 NgMock 模块时,我的真实 angular 应用程序并编写了一个简单的测试来测试我的一个控制器上的方法,我得到以下 stackTrace。

grunt karma:dev
Running "karma:dev" (karma) task
25 03 2016 20:41:24.754:INFO [karma]: Karma v0.13.22 server started at http://localhost:9876/
25 03 2016 20:41:24.763:INFO [launcher]: Starting browser Chrome
25 03 2016 20:41:24.771:INFO [launcher]: Starting browser Firefox
25 03 2016 20:41:28.747:INFO [Chrome 49.0.2623 (Windows 10 0.0.0)]: Connected on socket /#yRHoLsbEaJWHNtSDAAAA with id 47988329
Chrome 49.0.2623 (Windows 10 0.0.0) Unit tests del CRM:  Create new message Should create a text message with the correct structure FAILED
        TypeError: $scope.$on is not a function
            at new <anonymous> (C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/controllers/view-conversations.js:248:12)
            at e (C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/angular.min.js:39:156)
            at Object.instantiate (C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/angular.min.js:39:273)
            at C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/angular.min.js:80:228
            at C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/angular-mocks.js:1848:12
            at Context.<anonymous> (C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/test/frontend/leadaki-app-tests.js:44:30)
Chrome 49.0.2623 (Windows 10 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.087 secs / 0.024 secs)
Firefox 45.0.0 (Windows 10 0.0.0) Unit tests del CRM:  Create new message Should create a text message with the correct structure FAILED
        $scope.$on is not a function
        @C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/controllers/view-conversations.js:248:5
        e@C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/angular.min.js:39:154
        h/<.instantiate@C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/angular.min.js:39:273
        Xe/this.$get</<@C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/angular.min.js:80:226
        angular.mock.$ControllerDecorator</<@C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/public/dashboard/v4/js/angular-mocks.js:1848:12
        @C:/Users/Pablo/Data/software/workspace/intellij/leadaki-core/test/frontend/leadaki-app-tests.js:44:30

Chrome 49.0.2623 (Windows 10 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.087 secs / 0.024 secs)
Firefox 45.0.0 (Windows 10 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.053 secs / 0.011 secs)
Warning: Task "karma:dev" failed. Use --force to continue.

Aborted due to warnings.

ngMock 生成的 "mock" 范围似乎不接受监听器或类似的东西。

有没有人暗示这里可能是错误的?

我可以粘贴我所有的配置文件,但我认为这些信息太多,我不想淹没 post。让我知道是否需要任何其他信息,我会添加。

在此先致谢!

describe('Unit tests del CRM: ', function () {

    before(function() {
        if (window.__html__) {
            document.body.innerHTML = window.__html__['test/index.html'];
        }
    });

    beforeEach(angular.mock.module('appCliengo'));

    var $controller;
    var $rootScope;

    beforeEach(angular.mock.inject(function(_$rootScope_, _$controller_){
        $rootScope = _$rootScope_;
        $controller = _$controller_;
    }));

    describe('Create new message', function () {
        it('Should create a text message with the correct structure', function () {
            var $scope = {};
            var controller = $controller('Contacts.viewConversation', { $scope: $scope });

            var messageBody = 'Hola, me gustaria comprar un auto';
            var newTextMessage = $scope.createMessage('text/plain', '123456789', 'user', 'abcdefghijk', messageBody);

            expect(newTextMessage.body).to.equal(messageBody);
        });
    });
});

如果不查看您的确切设置很难说,但是您是否创建了一个作用域对象以注入到您的控制器中?

很多时候,您只需使用 $rootScope 对象就可以伪造它:

beforeEach(angular.mock.inject($injector => {
    $controller = $injector.get('$controller');
    rootScope = $injector.get('$rootScope');
}));

... test code ...

let controller = $controller('UserController', {$scope: rootScope});

... do stuff with controller ...

但是,您也可以使用 rootScope 创建一个新范围并将其输入。