Reputation: 3520
I am very new to testing in Javascript and am currenly trying to test a controller function. The function calls a service method which retrieves data from a web sql db.
This is a part of my controller function (it contains 2 callbacks, one for success and another for error):
$scope.getLocations = function () {
LocationDbService.getAll(
//Success
function (tx, results) {
$scope.numberOfLocations = results.rows.length;
...
},
//Error
function () {
console.log("Error");
});
}
The test:
it('we should be able to retrieve all stored locations',
function () {
expect(scope.numberOfLocations).toBeUndefined();
scope.getLocations();
expect(scope.numberOfLocations).toBeDefined();
});
beforeEach test:
var ctrl, scope, location, locationDbService;
// inject the $controller and $rootScope services
// in the beforeEach block
beforeEach(inject(function ($controller, $rootScope, $location, LocationDbService) {
// Create a new scope that's a child of the $rootScope
scope = $rootScope.$new();
// Create the controller
ctrl = $controller('LocationsCtrl', {
$scope: scope
});
location = $location;
locationDbService = LocationDbService;
}));
Controller header:
.controller('LocationsCtrl', function ($scope, $location, LocationDbService) {
When I run the application in the browser (or on my smartphone, its a hybrid app) everything works but when I run the test I get the following:
Does somebody know why the scoped variable is still undefined? Thanks in advance!
Upvotes: 1
Views: 2175
Reputation: 2249
When instantiating your controller, you should also inject any other services it needs.
AngularJS has a cool trick btw where you can use underscores in names:
beforeEach(inject(function ($controller, $rootScope, _$location_, _LocationDbService_) {
// Create a new scope that's a child of the $rootScope
scope = $rootScope.$new();
// Create the controller
ctrl = $controller('LocationsCtrl', {
$scope: scope,
$location : _$location_,
LocationDbService : _LocationDbService_
});
location = _$location_; //thx to the underscores you could use '$location' as name instead of 'location'
locationDbService = _LocationDbService_;
}));
Next you should mock the service call:
it('should be able to retrieve all stored locations',
function () {
spyOn(locationDbService , 'getAll').andCallFake(function (success, fail) {
var results = {};
results.rows = new Array(5);
success(null, results);
});
expect(scope.numberOfLocations).toBeUndefined();
scope.getLocations();
expect(scope.numberOfLocations).toBe(5);
});
The service should have tests of its own.
Upvotes: 1