2

所以我开始为我编写的 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});

线。我是否应该将此逻辑放在其他地方以便我可以对这段代码进行单元测试?

4

2 回答 2

6

我会将您要测试的所有这些代码移动到服务中,然后将其注入到运行块中。然后您可以独立测试此服务。然后,您还可以设置模块以更灵活地测试依赖于身份验证的其他内容。

于 2012-11-06T06:46:18.003 回答
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

于 2013-03-18T11:19:39.243 回答