所以我开始为我编写的AngularJS应用程序编写单元测试。此应用程序受登录页面保护,因此如果用户名未登录,则除登录页面之外的任何页面的任何请求都将重定向登录页面。这个逻辑是从主模块.run()方法执行的,因为它只需要运行一次,当应用程序启动时,有没有办法测试从主模块.run()方法中执行的代码?我是以下测试代码:
describe('Login Controller', function(){
'use strict';
var scope, controller, $httpBackend, $resource, callback;
beforeEach(module('application'));
beforeEach(inject(function($injector, $rootScope, $controller, $http, $location, authentication, session) {
$httpBackend = $injector.get('$httpBackend');
$httpBackend.expectGET('/api/v1/authentication').respond({status: 'success', data: null});
$resource = $injector.get('$resource');
callback = jasmine.createSpy();
scope = $rootScope.$new();
controller = new $controller('Login', {
$scope: scope,
$http: $http,
$location: $location,
authentication: authentication,
session: session
});
}));
afterEach(function() {
$httpBackend.verifyrifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
});
it('should verify all default values for controller', function() {
expect(scope.username).toEqual('');
expect(scope.password).toEqual('');
expect(scope.displayApplicationLoad).toEqual(false);
expect(angular.isFunction(scope.login)).toEqual(true);
expect(angular.isFunction(scope.logout)).toEqual(true);
expect(scope.loggedIn).toEqual(false);
expect(scope.headerTemplate).toEqual('/templates/core/header.html');
expect(scope.footerTemplate).toEqual('/templates/core/footer.html');
});
});
问题是主模块.run()方法内部运行的代码没有考虑到
$httpBackend.expectGET('/api/v1/authentication').respond({status: 'success', data: null});
线。我应该将此逻辑放在其他地方,以便我可以对此代码进行单元测试吗?
答案 0 :(得分:6)
我会将您要测试的所有代码移动到一个服务中,然后将其注入到运行块中。然后,您可以独立测试此服务。此外,您还可以设置模块,以便更灵活地测试依赖于身份验证的其他内容。
答案 1 :(得分:0)
我想我找到了一种测试模块运行方法的方法。这有点hacky但它完成了工作。这是我的解决方案:
describe( 'my module', function() {
var runBlocks;
beforeEach( function() {
var myModule = angular.module( 'modules.flow' );
runBlocks = myModule._runBlocks;
myModule._runBlocks = [];
module( 'myModule' );
} );
afterEach( function() {
angular.module( 'modules.flow' )._runBlocks = runBlocks;
} );
describe( 'when loaded', function() {
beforeEach( inject( function( $injector ) {
// Here you could e.g. configure $httpBackend
for( var i = 0; i < runBlocks.length; ++i ) {
$injector.invoke( runBlocks[i] );
}
} ) );
// Tests ...
} );
} );
首先,我复制为模块定义的所有运行块,并删除运行块的内部列表。然后可以进行运行块成功所需的设置,然后让注入器调用函数。
尽管如此,如果有机会将运行块中的代码提取到适当的服务中,您应该更喜欢这种方式。
更新:添加了缺失的afterEach
方法
更新2:修正了对angular.module