I have already read this post (and others) but I don't manage to make this simple unit test work. I'm using the version 2 of Jasmine. My factory is very simple:
angular.module('myApp')
.factory('detectPath', function ($location, $rootScope) {
'use strict';
var locationPath = $location.path()
function getPath () {
if (locationPath === '/') {
locationPath = 'home';
} else {
locationPath = '';
}
$rootScope.path = locationPath;
}
getPath();
return locationPath;
});
And my unit test is just as simple:
'use strict';
describe('Factory: detectPath', function () {
var detectPath, $rootScope, $location;
beforeEach(module('myApp'));
beforeEach(inject(function (_detectPath_, _$rootScope_, _$location_) {
detectPath = _detectPath_;
$rootScope = _$rootScope_;
$location = _$location_;
spyOn($location, 'path').and.returnValue('/');
}));
it('should return pathName', function ($location) {
expect($rootScope.path).toBe('home');
});
});
This doesn't pass the test (I get the error expect false to be "home").
What I am doing wrong? Is there a way to verify that spyOn has been called (only once)?
There are two main problems with your code.
First of all, your getPath()
function is executed before you are setting spy. You should either set the spy in the previous beforeEach
or inject your factory in the test (I went for the second solution).
The second problem (which does not influence the test yet) is that you hide your $location
variable with test's function argument - you will not be able to access it as it will always be undefined. After I removed this arg, I'm able to test if spy has been called with expect(...).toHaveBeenCalled()
.
Here is a working code:
describe('Factory: detectPath', function () {
var detectPath, $rootScope, $location;
beforeEach(module('myApp'));
beforeEach(inject(function (_$rootScope_, _$location_) {
$rootScope = _$rootScope_;
$location = _$location_;
spyOn($location, 'path').and.returnValue('/');
}));
it('should return pathName', function () {
inject(function (detectPath) {
expect($location.path).toHaveBeenCalled();
expect($rootScope.path).toBe('home');
});
});
});
And JSFiddle (using Jasmine 1.3 but the only difference in this sample is that you call and.returnValue
in Jasmine 2 and returnValue
in Jasmine 1.3).