2016-07-15 83 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'); 
    }); 

});