变量没有在Jasmine测试用例中定义,尽管它在作用域中
Variable not defined in Jasmine test case although its in scope
我想测试一个控制器,它监听一个事件来做一些事情。事件处理程序依赖于一个名为Main
的全局变量。我试图通过模拟所有依赖来单元测试事件监听器,但是Karma抛出错误:
ReferenceError: Main is not defined
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
来解决这个问题:
- 你可以在注册事件处理程序之前,或者在创建Angular模块之前(或者在控制器内部)做这个操作。
- 你可以在同一个模块中把
Main
变成一个Angular服务,把它注入你的控制器如下:
App.service('Main', function(){
});
App.controller('AppController', ['$scope', 'Main', function($scope, Main){
$scope.$on('$viewContentLoaded', function() {
Main.initComponents(); // init core components
});
}]);
相关文章:
- 在具有命名作用域的自定义Polymer元素中隐藏表行
- 如何在html中以角度显示自定义指令的作用域
- 如何在angularjs中将多个作用域变量传递到自定义指令中
- AngularJS:如何调用指令中定义的函数'控制器的作用域
- AngularJS:ngRepeat作用域在具有隔离作用域和ngTransclude的自定义指令中失败
- AngularJS指令中的作用域未定义,控制器中有ajax请求
- ReferenceError:regeneratorRuntime未定义(但在作用域内工作)
- 监视自定义指令属性在父作用域更改时不发生更改
- 在全局作用域中定义的具有相同名称的变量
- 角度:创建可以调用作用域函数的自定义指令
- AngularJS指令作用域未解析(“属性名称未定义”错误)
- $scope变量在指令隔离作用域中未定义
- AngularJS自定义指令在继承父作用域时访问模板中的属性
- 无法从具有隔离作用域的指令中访问控制器中定义的对象
- 在指令的隔离作用域中定义的调用函数
- 如何使 AngularJS 指令在不隔离作用域的情况下清楚地定义其依赖关系
- JavaScript 通过脚本标签定义作用域
- 在循环作用域中定义变量或应超出作用域
- 如何从事件处理程序调用 AngularJS 作用域定义的函数
- 使用模块全局作用域定义可从prototype访问的私有类字段