问题
Hi I am building an app using AngularJS
and now I am on to the unit testing my application. I know how to write unit test cases for services, controllers etc. But I don't know to write it for $routeChangeStart
.
I have following code in my app.js
app.run(function ($rootScope, $location, AuthenticationService) {
$rootScope.$on('$routeChangeStart', function () {
if (AuthenticationService.isLoggedIn()) {
$rootScope.Authenticated = 'true';
$rootScope.Identity = localStorage.getItem('identification_id');
} else {
$rootScope.Authenticated = 'false';
$rootScope.Identity = localStorage.removeItem('identification_id');
}
});
});
I have written this code to find out whether the user is logged in or not for each routing in my app. I have written a service AuthenticationService
for this purpose like;
app.factory('AuthenticationService', function (SessionService) {
return {
isLoggedIn: function () {
return SessionService.get('session_id');
}
};
});
And my session service like;
app.factory('SessionService', function () {
return {
get: function (key) {
return localStorage.getItem(key);
}
};
});
I am using Jasmine
to write test cases and using Istanbul
for code coverage. When I run my test using Grunt
I am getting something like this in my app.js;
It's because I am not covering these statements in my test cases as I don't know how to write test case for this particular piece of code. Any suggestions?
回答1:
That run
block runs every time the module is loaded, so that listener is being registered during the tests. You just need that event to actually be sent so that you can test the code within it. Something like this should do the trick:
it("should test the $routeChangeStart listener", inject(function($rootScope) {
$rootScope.$broadcast("$routeChangeStart");
//expects for the listener
}));
See How can I test events in angular? for how to test events in general.
回答2:
A good way to test $rootScope.$on('$routeChangeStart',...
may be found in the unit tests of angularjs itself. It is an excellent source of knowledge as every feature is tested, so it's possible to find good solutions. That's why unit test is so great, isn't it ?
https://github.com/angular/angular.js/blob/master/test/ngRoute/routeSpec.js
The following test (taken from angular head 1.2.x - follow the link for latest) works great, you just have to adapt to your test (as the event handler is already in your code):
'use strict';
describe('$route', function() {
var $httpBackend;
beforeEach(module('ngRoute'));
beforeEach(module(function() {
return function(_$httpBackend_) {
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', 'Chapter.html').respond('chapter');
$httpBackend.when('GET', 'test.html').respond('test');
$httpBackend.when('GET', 'foo.html').respond('foo');
$httpBackend.when('GET', 'baz.html').respond('baz');
$httpBackend.when('GET', 'bar.html').respond('bar');
$httpBackend.when('GET', 'http://example.com/trusted-template.html').respond('cross domain trusted template');
$httpBackend.when('GET', '404.html').respond('not found');
};
}));
it('should route and fire change event', function() {
var log = '',
lastRoute,
nextRoute;
module(function($routeProvider) {
$routeProvider.when('/Book/:book/Chapter/:chapter',
{controller: angular.noop, templateUrl: 'Chapter.html'});
$routeProvider.when('/Blank', {});
});
inject(function($route, $location, $rootScope) {
$rootScope.$on('$routeChangeStart', function(event, next, current) {
log += 'before();';
expect(current).toBe($route.current);
lastRoute = current;
nextRoute = next;
});
$rootScope.$on('$routeChangeSuccess', function(event, current, last) {
log += 'after();';
expect(current).toBe($route.current);
expect(lastRoute).toBe(last);
expect(nextRoute).toBe(current);
});
$location.path('/Book/Moby/Chapter/Intro').search('p=123');
$rootScope.$digest();
$httpBackend.flush();
expect(log).toEqual('before();after();');
expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'});
log = '';
$location.path('/Blank').search('ignore');
$rootScope.$digest();
expect(log).toEqual('before();after();');
expect($route.current.params).toEqual({ignore:true});
log = '';
$location.path('/NONE');
$rootScope.$digest();
expect(log).toEqual('before();after();');
expect($route.current).toEqual(null);
});
});
来源:https://stackoverflow.com/questions/19093010/jasmine-unit-test-case-for-routechangestart-in-angularjs