2016-07-15 7 views
1

私はカルマでユニットテストの周りに頭を上げています。私は状態遷移をチェックしたいので、このテストを作成しました。アプリはlanding州に行くと始まり、そこからmainに行きたいと思っています。これは、そうloginにリダイレクトされます安全なルートである:私は私のapp.jsでテストの状態遷移を角度で単位化する方法は?

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

$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のrefの:https://github.com/dimitri-a/basic_karma

答えて

0

次の2つの異なるものをテストしようとしているかのように思えます。まず、$stateChangeStart -eventが起動するかどうかをテストしています。次に、必要に応じてリダイレクトする場合、カスタムハンドラとその中のロジックをテストしています。

ユニットテストは、アプリケーションの小さな部分をテストすることです。 $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のアプリケーションをテストしていないので、$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'); 
    }); 

}); 
関連する問題