问题
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 vm
in 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