Angularjs 使用$stateChangeStart和$rootScope测试UI路由器状态

Angularjs 使用$stateChangeStart和$rootScope测试UI路由器状态,angularjs,testing,angular-ui-router,Angularjs,Testing,Angular Ui Router,如何使用$stateChangeStart或其他发出的事件进行测试 我有以下代码,本质上检查用户是否登录,如果没有,则重定向到app.login状态 app.run(function ($rootScope, $state, AuthenticationService) { $rootScope.AuthenticationService = AuthenticationService $rootScope.isLoggedIn = AuthenticationService.getI

如何使用$stateChangeStart或其他发出的事件进行测试

我有以下代码,本质上检查用户是否登录,如果没有,则重定向到
app.login
状态

app.run(function ($rootScope, $state, AuthenticationService) {

  $rootScope.AuthenticationService = AuthenticationService
  $rootScope.isLoggedIn = AuthenticationService.getIsLoggedIn

  if (!$rootScope.isLoggedIn()) {
    $state.go('app.login')
  }
  // Catch all errors on state change
  $rootScope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) {
    $state.go('app.home')
  })

  // Sets up the role requirements per state
  $rootScope.$on('$stateChangeStart', function (event, toState) {
    if (AuthenticationService.getIsLoggedIn()) {
    } else {
      if (toState && toState.name !== 'app.login') {
        $state.go('app.login')
      }
    }
  })
})
我试图实现的测试:

'use strict'

describe('Controller', function () {

  var $scope
    , $state
    , $rootScope
    , AuthenticationService
    , $controller

  beforeEach(module('replanApp'))

  beforeEach(inject(function ($injector) {
    $state = $injector.get('$state')
    $rootScope = $injector.get('$rootScope')
    AuthenticationService = $injector.get('AuthenticationService')
    $scope = $rootScope.$new()
    $controller = $injector.get('$controller')
  }))

  describe('Initializers', function () {
    it('should redirect to /login if the user is not logged in', function () {
      $state.go('app.admin.index')
      $rootScope.$apply()
      assert.notOk(AuthenticationService.getIsLoggedIn())
      assert.equal($state.current.name, 'app.login')
    })
  })
})
它基本上应该进入一个状态,然后
$rootScope.$on('$stateChangeStart',fn(){})
应该可以看到用户没有登录,并将其转移到
app.login
状态

但我得到的断言错误:预期'app.admin.index'等于'app.login'


如何使用$stateChangeStart和其他事件实现测试?

我将修改测试,以检查是否使用
'app.login'
调用了
$state.go
,而不是尝试检查当前状态:

describe('Initializers', function () {
    beforeEach(function(){
        spyOn($state,'go');
    });
    it('should redirect to /login if the user is not logged in', function () {
      $state.transitionTo('app.admin.index');
      $rootScope.$apply();
      assert.notOk(AuthenticationService.getIsLoggedIn());
      expect($state.go).toHaveBeenCalledWith('app.login');
    });
  });

我不能保证这将修复您的测试,但这将使它更像是一个单元测试,因为它不依赖于
$state.go
来设置当前状态。

顺便说一句,您必须调用
事件.preventDefault()
$state.go('app.login')
之前。执行此操作时,我得到“预期spy已被['app.login']调用,但实际调用是['app.admin.index']…编辑后使用$scope.transitiono停止测试失败,出现上述错误。”+1建议检查$state.go调用,而不是状态更改本身,这是从几十个其他建议中唯一对我有效的方法,作为一个单元测试,它更有意义。