angularjs jasmine tests:找不到变量vm

时间:2016-04-08 21:49:01

标签: angularjs unit-testing jasmine

棱角分明的角度和茉莉花测试新手。所以我正在编写一个示例单元测试,以便在我的控制器中初始化时测试一个数组的长度。我希望数组长度为0.但是,不确定我缺少什么,测试输出说它找不到我用来引用数组的变量vm。这是我的测试:

(function(){
'use strict';
describe('Testing UploadedReleasesController', function() {

    beforeEach(module('app.uploadedReleases'));

    describe('Testing uploaded releases controller', function(){
        var vm, controller;

        beforeEach(inject(function($controller, $rootScope){
            vm = $rootScope.$new();
            controller = $controller('UploadedReleasesController', {$scope:vm});
        }));
    });

    describe('album length', function(){
        it('it should test album length', function () {
            expect(vm.albums).toBeDefined();
            expect(vm.albums.length).toBe(0);
        });
    });

  });

})();

输出:Testing UploadedReleasesController album length it should test album length FAILED ReferenceError: Can't find variable: vm 有什么建议吗?

修改 在其他响应之后,我修改了我的.spec文件,并且vm无法找到的错误消失了。但现在我有一个不同的错误。以下是更新后的代码:

(function(){
'use strict';
describe('Testing UploadedReleasesController', function() {
    var scope, controller;
    beforeEach(inject(function($controller, $rootScope){
        scope = $rootScope.$new();
        controller = $controller('UploadedReleasesController', {$scope:scope});
    }));
    beforeEach(module('app.uploadedReleases'));

    describe('album length', function(){
        it('it should test album length', function () {
            //expect(vm.albums).toBeDefined();
            expect(scope.albums.length).toBe(0);
        });
    });


   });

})();

Error:  `PhantomJS 1.9.8 (Mac OS X 0.0.0) Testing UploadedReleasesController true Should be true FAILED
Error: [ng:areq] Argument 'UploadedReleasesController' is not a function, got undefined
http://errors.angularjs.org/1.3.20/ng/areq?p0=UploadedReleasesController&p1=not%20a%20function%2C%20got%20undefined
undefined
    at assertArg (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:1590)
    at assertArgFn (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:1601)
    at /Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:8493
    at /Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular-mocks/angular-mocks.js:1916
    at /Users/rgoti/ingestion/external-ingestion/app/public/src/app/uploadedReleases/uploaded-releases.controller.spec.js:10
    at invoke (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:4219)
    at workFn (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular-mocks/angular-mocks.js:2475)
Error: Injector already created, can not register a module!`

另一个编辑:添加了Oscar的解决方案,使之前的错误消失。现在我有另一个问题。 HEre是我的实际控制器定义:

(function (){

angular.module('app.uploadedReleases')
        .controller('UploadedReleasesController', UploadedReleasesController)
        .controller('ModalController', ModalController);

var ACTION = {
    CANCEL: 0,
    SAVE: 1,
    DELETE: 2,
    SUBMIT: 3
};

UploadedReleasesController.$inject = ['$log', '$scope', '$modal', 'ReleaseService', 'TrackService', 'APP_CONFIG'];
function UploadedReleasesController ($log, $scope, $modal, releaseService, trackService, APP_CONFIG){

因此我的spec文件中没有ModalController。这就是我收到以下错误的原因吗?

`Error: [$injector:unpr] Unknown provider: $modalProvider <- $modal <- UploadedReleasesController
http://errors.angularjs.org/1.3.20/$injector/unpr?p0=%24modalProvider%20%3C-%20%24modal%20%3C-%20UploadedReleasesController
    at /Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:4031
    at getService (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:4178)
    at /Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:4036
    at getService (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:4178)
    at invoke (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:4210)
    at instantiate (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:4227)
    at /Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:8524
    at /Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular-mocks/angular-mocks.js:1916
    at /Users/rgoti/ingestion/external-ingestion/app/public/src/app/uploadedReleases/uploaded-releases.controller.spec.js:12
    at invoke (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular/angular.js:4219)
    at workFn (/Users/rgoti/ingestion/external-ingestion/app/public/bower_components/angular-mocks/angular-mocks.js:2475)
undefined
Expected undefined to be defined.
    at /Users/rgoti/ingestion/external-ingestion/app/public/src/app/uploadedReleases/uploaded-releases.controller.spec.js:22
TypeError: 'undefined' is not an object (evaluating 'vm.albums.length')
    at /Users/rgoti/ingestion/external-ingestion/app/public/src/app/uploa`

是这样,我该如何解决?

4 个答案:

答案 0 :(得分:1)

您必须先在外部范围中定义vm

(function(){
'use strict';
describe('Testing UploadedReleasesController', function() {
    var vm, controller;

    beforeEach(module('app.uploadedReleases'));

    describe('Testing uploaded releases controller', function(){
        beforeEach(inject(function($controller, $rootScope){
            vm = $rootScope.$new();
            controller = $controller('UploadedReleasesController', {$scope:vm});
        }));
    });

    describe('album length', function(){
        it('it should test album length', function () {
            expect(vm.albums).toBeDefined();
            expect(vm.albums.length).toBe(0);
        });
    });

  });

})();

答案 1 :(得分:1)

嗯,您在第一个describe()函数中定义了vm,并且您在第二个函数中使用它。所以它确实是未定义的。变量的范围是它们的封闭函数。

另外,你不应该为#34; Scope&#34;类型的变量命名。 vmvm通常用于表示当前控制器,而不是其范围。使用...... $ scope。

答案 2 :(得分:1)

beforeEach(inject....直接移到describe('Testing UploadedReleasesController'内并实例化变量:var vm, controller;

describe('Testing UploadedReleasesController', function() {
    var vm, controller;
    beforeEach(inject(....

将在内部套件中的每个测试中运行“root”套件(Testing UploadedReleasesController)中的每个之前。内部套件还将具有vm,并且控制器变量可用。另外,我会创建一个afterEach函数,将变量重置为undefined

更新: 将'album length'套件移到'Testing uploaded releases controller'中:

(function(){
'use strict';
describe('Testing UploadedReleasesController', function() {

    beforeEach(module('app.uploadedReleases'));

    describe('Testing uploaded releases controller', function(){
        var vm, controller;

        beforeEach(inject(function($controller, $rootScope){
            vm = $rootScope.$new();
            controller = $controller('UploadedReleasesController', {$scope:vm});
        }));

        afterEach(function() {
            vm = undefined;
            controller = undefined;
        });

        describe('album length', function(){
            it('it should test album length', function () {
                expect(vm.albums).toBeDefined();
                expect(vm.albums.length).toBe(0);
            });
        });
    });

  });

})();

答案 3 :(得分:1)

您的两个内部描述功能彼此处于同一级别。 vm变量不在第二个范围内。

将第二个嵌套在第一个内部。这就是我认为你想要的。像这样:

describe('Testing uploaded releases controller', function(){
        var vm, controller;

        beforeEach(inject(function($controller, $rootScope){
            vm = $rootScope.$new();
            controller = $controller('UploadedReleasesController', {$scope:vm});
        }));
        describe('album length', function(){
            it('it should test album length', function () {
                expect(vm.albums).toBeDefined();
                expect(vm.albums.length).toBe(0);
            });
        });
    });

或者将第一个(“测试上传的...”)之外的vm变量声明拉到顶级描述中。