angularjs jasmine tests: Variable vm not found

走远了吗. 提交于 2019-12-23 05:11:27

问题


New to angular and Jasmine tests in angular. So I am writing a sample unit test to test a length of an array upon initialization in my controller. I expect the array to be of length 0. However, not sure what I am missing, the test output says that it cannot find the variable vm I am using to refer to the array. Here is my test:

(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);
        });
    });

  });

})();

Output: Testing UploadedReleasesController album length it should test album length FAILED ReferenceError: Can't find variable: vm Any suggestions ?

EDIT After other responses, I modified my .spec file and the error of vm not being able to find goes away. But now I have a different error. Here is the updated code:

(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!`

ANOTHER EDIT: Added Oscar's solution which makes the previous error go away. Now I have another problem. HEre is my actual controller definition:

(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){

So ModalController is not there in my spec file. Is that why I get the following error ?

`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`

Is so, how do I resolve it ?


回答1:


You have to define vm earlier in the outer scope:

(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);
        });
    });

  });

})();



回答2:


Well, you're defining vmin the first describe() function, and you're using it in the second one. So it's indeed undefines. Variables are scoped to their enclosing functions.

Also, you shouldn't name a variable of type "Scope" vm. vm is typically used to refer to the current controller, not to its scope. Use... $scope.




回答3:


Your two inner describe functions are at the same level as one another. The vm variable isn't in scope for the second one.

Either nest the second one inside the first. That's what I think you want. Something like this:

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);
            });
        });
    });

Or pull the vm variable declaration outside of the first ("'Testing uploaded...") into the top level describe.




回答4:


Move the beforeEach(inject.... directly inside describe('Testing UploadedReleasesController' and instantiate the variables: var vm, controller;

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

The before each in the 'root' suite (Testing UploadedReleasesController) will be run for each test in the the inner suites. The inner suites will also have the vm, and controller variables availalbe. Additionally, I would create an afterEach function that resets the variables to undefined.

Update: Move the 'album length' suite inside '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);
            });
        });
    });

  });

})();


来源:https://stackoverflow.com/questions/36509878/angularjs-jasmine-tests-variable-vm-not-found

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!