变量没有在Jasmine测试用例中定义,尽管它在作用域中

Variable not defined in Jasmine test case although its in scope

本文关键字:作用域 定义 Jasmine 测试用例 变量      更新时间:2023-09-26

我想测试一个控制器,它监听一个事件来做一些事情。事件处理程序依赖于一个名为Main全局变量。我试图通过模拟所有依赖来单元测试事件监听器,但是Karma抛出错误:

ReferenceError: Main is not defined

Angular代码:
App.controller('AppController', ['$scope', function($scope){
    $scope.$on('$viewContentLoaded', function() {
        Main.initComponents(); // init core components
    });
}]);

规范文件:

describe("App", function () {
    var scope, AppController, Main;
    describe("Login", function () {
        beforeEach(module("App"));
        beforeEach(inject(['$rootScope', '$controller', function($rootScope, $controller){
            scope = $rootScope.$new();
            Main = jasmine.createSpyObj("Main",["initComponents"]);
            AppController = $controller('AppController', {$scope : scope});
        }]));
        it("should call initComponents() on Main module on $viewContentLoaded event", inject(['$rootScope', function ($rootScope) {
            $rootScope.$broadcast('$viewContentLoaded');
            expect(Main.initComponents).toHaveBeenCalled();
        }]));
    });
});

karma.conf.js:

module.exports = function(config){
    config.set({
        basePath : './',
        files : [
            'app/bower_components/angular/angular.js',
            'app/bower_components/oclazyload/dist/oclazyLoad.min.js',
            'app/bower_components/angular-ui-router/release/angular-ui-router.min.js',
            'app/bower_components/angular-mocks/angular-mocks.js',
            'app/**/app.js',
            'app/**/controllers.js',
            'app/**/services.js',
            'app/**/directives.js',
            'app/**/filters.js',
            'app/**/routes.js',
            'app/**/specs.js'
        ],
        autoWatch : true,
        frameworks: ['jasmine'],
        browsers : ['Chrome'],
        plugins : [
            'karma-chrome-launcher',
            'karma-firefox-launcher',
            'karma-jasmine',
            'karma-junit-reporter'
        ],
        junitReporter : {
            outputFile: 'test_out/unit.xml',
            suite: 'unit'
        }
    });
};

有什么问题吗?谢谢你的帮助。

这是一个变量可见性问题,因为这些变量的定义范围。

对于您的$viewContentLoaded处理程序正常工作,它需要一个Main对象,该对象是NOT在当前范围或在范围链中的任何父范围中定义的。使用createSpyObj创建的Main模拟对象位于使用describe()定义的App测试套件的范围内。如果你看一下你的代码,

describe("App", function () {
    var scope, AppController, Main; 
    /* remaining code */
}

从上面可以看到,Main是定义在describe()方法,因此它仅在该函数或to中可用在此函数中定义的所有子函数

describe()之外的任何函数,比如Main JS中的事件处理程序($on)都不会知道它的存在。这就是调用该处理程序时出现错误的原因。

您可以通过以下两种方式正确初始化Main来解决这个问题:

  1. 你可以在注册事件处理程序之前,或者在创建Angular模块之前(或者在控制器内部)做这个操作。
  2. 你可以在同一个模块中把Main变成一个Angular服务,把它注入你的控制器如下:
主要JS

 App.service('Main', function(){
 });
 App.controller('AppController', ['$scope', 'Main', function($scope, Main){
        $scope.$on('$viewContentLoaded', function() {
            Main.initComponents(); // init core components
        });
 }]);