How do I test variables local to an Angular controller in Jasmine
Solution 1
In your jasmine spec, first create the controller:
var ctrl;
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
ctrl = $controller('myController', {
$scope: scope
});
}));
Then you can access its properties by doing ctrl.pagesById
. Of course, rather than doing var pagesById
you'll need to use this.pagesById
in your controller.
Solution 2
Here is my way for testing local variables in Angular methods:
//------- Function for getting value of local variables
function getLocalVariable(sLocalVarName, obj, method, args){
method = method.toString();
let changedMethod = method.substring(0, method.lastIndexOf("}")) + ";" + "return " + sLocalVarName + "}";
eval(' changedMethod = ' + changedMethod);
return changedMethod.call(obj, args)
}
//----------- service
class assignStuffService {
getAvaliableStuff(shift) {
const params = {
agency_id: 0 ,
start_time: shift.data.shift.start_time,
end_time : shift.data.shift.end_time
};
}
}
//----------- part of spec
it('should set values to "params" object props', () => {
let shift = {
data:{
shift:{
start_time:'',
end_time:''
}
}
};
let params = getLocalVariable('params',
assignStuffService,
assignStuffService.getAvaliableStuff,
shift);
expect(params).toEqual({
agency_id: 0 ,
start_time: shift.data.shift.start_time,
end_time : shift.data.shift.end_time
});
});
akronymn
Equal parts explorer and technologist. Lover of good design and intelligent interfaces. Consumer of APIs. Developer of the web. Builder of products. Photographer. Gourmet and gourmand. Local political junky. Serious casual gamer. Wanderer. Hobby collector.
Updated on June 23, 2022Comments
-
akronymn about 2 years
I have a controller with a local variable
function IndexCtrl($scope) { var pagesById = []; loadPages(); // snip function loadPages() { // pagesById gets populated } // snip }
I'd like to test that pagesById is correctly populated but I'm not sure how to get at it from my it(). I don't need this variable to be in the $scope, it's just an intermediate set of information, so if I can avoid adding it to $scope that would be ideal.
it('scope.pages should populated based on pages data.', function() { $httpBackend.flush(); expect(pagesById).toEqualData(mock_page_results); });
gives me
ReferenceError: pagesById is not defined
Do I have any other options besides attaching it to $scope?
-
akronymn over 11 yearsthat makes sense but I get TypeError: Cannot read property 'pagesById' of undefined referring to the first line in my controller where I try to read this.pagesById
-
wless1 over 11 years
this
is probably different in the scope where you're accessing it. In the first line of your controller, dovar that = this;
, and then accesspagesById
usingthat.pagesById
-
akronymn over 11 yearsheh - this is starting to look like a doctor seuss story. It worked though. I'm surprised that 'this' isn't in scope inside of a member function. Oh well Thank you. +1 vote and +1 green check!
-
wless1 over 11 yearsheh. For more info on javascript scope: coding.smashingmagazine.com/2009/08/01/…
-
Robert over 11 yearsI don't think that this is the appropriated way to test. You want to test the resulting scope, not the controller. Check stackoverflow.com/questions/14202767/… for more info.
-
wless1 over 11 yearsThere are times when your controller has data that you don't want to put on the scope...