2016-07-15 43 views
1

我正忙于单元测试与业力。我想检查状态转换,所以我创建了这个测试。该应用程序首先进入landing状态,从那里我想去main。这是一个安全的路由,这样被重定向到login如何以角度单位测试statetransition?

it('should go to loginpage before main', function() { 
    $scope.$apply(); 
    expect($state.current.name).toBe('landing');  
    $state.transitionTo('main'); 
    $scope.$apply(); 
    expect($state.current.name).toBe('login'); 
}); 

在我app.js我:

$rootScope.$on('$stateChangeStart', function (event,next) { 
     console.log('statechange from:', $state.current.name) 
     //console.log('statechange to:',$state) 

     if (!next.authenticate) { 
      return; 
     } 

     //if next state is secure then check whether user is logged in: 

     if (next.authenticate) { 
      event.preventDefault(); 
      $state.transitionTo('login'); 
      console.log('goto login'); 
     } 


    }); 

当我运行我的测试与因果报应,我得到:

Chrome 51.0.2704 (Mac OS X 10.11.4) secure tests should go to loginpage before main FAILED 
    Expected '' to be 'landing'. 
     at Object.<anonymous> (/Users/dimitri/karma/basic_karma/appSpec.js:23:37) 
    Expected '' to be 'login'. 

为什么$state.current.name是空的?

github上裁判:https://github.com/dimitri-a/basic_karma

回答

0

看来,如果你想测试两个不同的东西。首先,您正在测试是否触发了$stateChangeStart事件。其次,如果在需要时重定向,则会测试自定义处理程序和逻辑。

单元测试是关于测试应用程序的一小部分。 $stateChangeStart -event不属于你的应用程序,因为它是ui-router组件的一部分。测试这个事件是否引发不是你的责任。更好; ui-router制作了自己的测试用例,用于检测$stateChangeStart是否被解雇。你可以亲自看到他们right here。您可以确定事件在需要时被触发。

那么,我们如何测试自己的定制逻辑呢?首先,我们需要重构$rootScope.$on处理程序。

$rootScope.$on('$stateChangeStart', handleStateChange); 

function handleStateChange(event, next) { 
    console.log('statechange from:', $state.current.name) 
    //console.log('statechange to:',$state) 

    if (!next.authenticate) { 
     return; 
    } 

    //if next state is secure then check whether user is logged in: 

    if (next.authenticate) { 
     event.preventDefault(); 
     $state.transitionTo('login'); 
     console.log('goto login'); 
    } 
} 

这样,我们去耦您自定义逻辑从角$rootScope,我们可以通过自身测试逻辑。别担心,当一个国家即将改变时,你的逻辑仍然会运行。

接下来是测试本身。我们不必处理$state.transitionTo,因为我们没有测试应用程序的这一部分(同样,ui-router有自己的测试$state.transitionTo)。我们甚至不需要使用$scope.$apply

describe('handleStateChange()', function() { 

    var $state; 

    beforeEach(inject(function(_$state_) { 
     $state   = _$state_; 

     // we spy on the $state.transitionTo method, to check if it 
     // has been called by our test case. 
     spyOn($state, 'transitionTo'); 
    })); 

    it('should transition to login state when authenticate:true', function() { 
     // arrange 
     var next = { 
      name: 'main', 
      authenticate: true 
     }; 

     // act 
     handleStateChange({}, next); 

     // assert 
     // in case of authenticate: true, $state.transitionTo should 
     // have been called with the 'login' name 
     expect($state.transitionTo).toHaveBeenCalledWith('login'); 
    }); 

    it('should not transition to login state when authenticate:false', function() { 
     // arrange 
     var next = { 
      name: 'landing', 
      authenticate: false 
     }; 

     // act 
     handleStateChange({}, next); 

     // assert 
     expect($state.transitionTo).not.toHaveBeenCalledWith('login'); 
    }); 

});