5

嗨,我正在使用构建一个应用程序AngularJS,现在我正在对我的应用程序进行单元测试。我知道如何为服务、控制器等编写单元测试用例。但我不知道如何为$routeChangeStart.

我的 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');
        }
    });
});

我编写了这段代码来确定用户是否为我的应用程序中的每个路由登录。我AuthenticationService为此目的编写了一项服务,例如;

app.factory('AuthenticationService', function (SessionService) {
    return {
        isLoggedIn: function () {
            return SessionService.get('session_id');
        }
    };
});

我的会话服务喜欢;

app.factory('SessionService', function () {
    return {
        get: function (key) {
            return localStorage.getItem(key);
        }
    };
});

Jasmine用来编写测试用例并Istanbul用于代码覆盖率。当我使用运行测试Grunt时,我的 app.js 中出现了类似的内容;

在此处输入图像描述

这是因为我没有在我的测试用例中涵盖这些语句,因为我不知道如何为这段特定的代码编写测试用例。有什么建议么?

4

2 回答 2

8

run每次加载模块时都会运行该块,以便在测试期间注册侦听器。您只需要实际发送该事件,以便您可以测试其中的代码。这样的事情应该可以解决问题:

it("should test the $routeChangeStart listener", inject(function($rootScope) {
   $rootScope.$broadcast("$routeChangeStart");
   //expects for the listener
}));

请参阅如何以角度测试事件?一般如何测试事件。

于 2013-09-30T21:34:13.740 回答
2

$rootScope.$on('$routeChangeStart',...可以在 angularjs 本身的单元测试中找到一个很好的测试方法。它是一个极好的知识来源,因为每个功能都经过测试,因此可以找到好的解决方案。这就是为什么单元测试如此出色的原因,不是吗?

https://github.com/angular/angular.js/blob/master/test/ngRoute/routeSpec.js

以下测试(取自 angular head 1.2.x - 点击链接获取最新版本)效果很好,您只需要适应您的测试(因为事件处理程序已经在您的代码中):

'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);
    });
  });
于 2014-02-26T16:01:34.357 回答