Angularjs 如何在angular中单元测试StateTransformation?

Angularjs 如何在angular中单元测试StateTransformation?,angularjs,unit-testing,angular-ui-router,karma-jasmine,Angularjs,Unit Testing,Angular Ui Router,Karma Jasmine,我正在用因果报应进行单元测试。我想检查状态转换,所以我创建了这个测试。应用程序首先进入登录状态,然后我想从那里进入main。这是一个安全路由,因此会被重定向到登录: it('should go to loginpage before main', function () { $scope.$apply(); expect($state.current.name).toBe('landing'); $state.transitionTo('main');

我正在用因果报应进行单元测试。我想检查状态转换,所以我创建了这个测试。应用程序首先进入
登录
状态,然后我想从那里进入
main
。这是一个安全路由,因此会被重定向到
登录

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'.
Chrome 51.0.2704(Mac OS X 10.11.4)安全测试应在main失败之前转到loginpage
预期“”为“着陆”。

在对象上。

似乎您正在尝试测试两个不同的东西。首先,您要测试
$stateChangeStart
-事件是否被触发。其次,您正在测试自定义处理程序和其中的逻辑,如果它在需要时重定向

单元测试是关于测试应用程序的一小部分。
$stateChangeStart
-事件不是应用程序的一部分,因为它是ui路由器组件的一部分。测试此事件是否触发不是您的责任。甚至更好;ui路由器制作了自己的测试用例,用于检查是否触发了
$stateChangeStart
。你可以自己看。您可以相当肯定,事件会在需要时触发

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

$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');
    }
}
通过这种方式,我们将自定义逻辑与Angular
$rootScope
解耦,并且我们可以自己测试逻辑。别担心,当状态即将改变时,您的逻辑仍将运行

接下来是测试本身。我们不必处理
$state.transitiono
,因为我们不测试应用程序的这一部分(同样,ui路由器有自己的
$state.transitiono
)。我们甚至不需要使用
$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');
    });

});

似乎你在尝试测试两种不同的东西。首先,您要测试
$stateChangeStart
-事件是否被触发。其次,您正在测试自定义处理程序和其中的逻辑,如果它在需要时重定向

单元测试是关于测试应用程序的一小部分。
$stateChangeStart
-事件不是应用程序的一部分,因为它是ui路由器组件的一部分。测试此事件是否触发不是您的责任。甚至更好;ui路由器制作了自己的测试用例,用于检查是否触发了
$stateChangeStart
。你可以自己看。您可以相当肯定,事件会在需要时触发

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

$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');
    }
}
通过这种方式,我们将自定义逻辑与Angular
$rootScope
解耦,并且我们可以自己测试逻辑。别担心,当状态即将改变时,您的逻辑仍将运行

接下来是测试本身。我们不必处理
$state.transitiono
,因为我们不测试应用程序的这一部分(同样,ui路由器有自己的
$state.transitiono
)。我们甚至不需要使用
$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');
    });

});