为什么在AngularJS控制器的单元测试中不会改变状态?

时间:2014-05-30 17:19:56

标签: angularjs angular-ui-router karma-runner

我正在使用Angular-ui Router而不是$ routeProvider。我的控制器是:

myApp.controller('LoginController', [
  '$scope', '$rootScope', '$state', 'userService', function($scope, $rootScope, $state, userService) {
    $scope.init = function() {
      $rootScope.pageTitle = 'Login';
      $scope.auth = {};
      return $scope.errors = null;
    };
    $scope.login = function() {
      return userService.login($scope.auth).then(function(response) {
        console.log(response);
        if (response.authenticated === true) {
          console.log("Movin states!");
          return $state.go('dashboard');
        } else {
          return $scope.errors = {
            message: 'Invalid credentials',
            type: 'error'
          };
        }
      });
    };
    return $scope.init();
  }
]);

在我的测试中,我正在做:

it('should properly authenticate a user', function() {
  $scope.init();
  $scope.auth = {
    username: 'test@test.com',
    password: 'mypassword'
  };
  $scope.login();
  deferred.resolve({
    authenticated: true
  });
  $rootScope.$apply();
  expect($state.current.name).toEqual('dashboard');
});

但是,$state.current.name保持为''。为什么不更新?

2 个答案:

答案 0 :(得分:2)

试试这个plunker

 beforeEach(inject(function($rootScope, $controller, userService,$q,$state) {
    $scope = $rootScope.$new();

    ctrl = $controller('LoginController', {
      $scope: $scope,
      $rootScope:$rootScope,
      userService:userService,
      $state:$state
    });

    _userService = userService;
    _$q = $q;
    _$state = $state;

  }));

  it('should properly authenticate a user', function() {
   // $scope.init();
   // $scope.auth = {
  //    username: 'test@test.com',
  //    password: 'mypassword'
  //  };

    //Set up
    var deferred = _$q.defer();
    spyOn(_userService,"login").and.callFake(function(){//fake the real implementation 
      //we don't need parameters in our fake function.
      //we only care about our return value.   
         return deferred.promise;
    }); 
    spyOn(_$state,"go"); //mock the $state.go method so that we can verify whether it was called.

    $scope.login();
    deferred.resolve({
      authenticated: true
    });

    $scope.$digest();
    expect(_$state.go).toHaveBeenCalledWith('dashboard');//verify
  });

需要注意的一些要点:

  • 单元测试应隔离彼此其他实际实现。因此,在设置测试时,测试不应依赖$scope.init();来设置测试。此实现可能会发生变化,这可能会无意中导致测试失败。

  • 您应该测试$state.current.name是否使用正确的参数进行测试,而不是测试$state.go,因为它更直接。

答案 1 :(得分:0)

你已经搞乱了控制器中的所有内容,请尝试以结构化格式下面的内容进行登录:

  var app = angular.module('app', [...Define dependencies here..]);

    //Contant For Login Process

       app.constant(

                'AUTH_EVENTS', {
                   loginSuccess: 'auth-login-success',
                   loginFailed: 'auth-login-failed',
                   logoutSuccess: 'auth-logout-success',
                   sessionTimeout: 'auth-session-timeout',
                   notAuthenticated: 'auth-not-authenticated',
                   notAuthorized: 'auth-not-authorized'
                }
       )

//Service to maintain User Session after Login

        .service('Session', function () {

            this.setSession = function(sessionId, userId, userRole){
                this.id = sessionId;
                this.userId = userId;
                this.userRole = userRole;    
            };
            this.create = function (sessionId, userId, userRole) {

              localStorage.setItem("sessionId" , sessionId);
              localStorage.setItem("userId" , userId);
              localStorage.setItem("userRole" , userRole);
              this.setSession(sessionId, userId, userRole);

            };
            this.destroy = function () {
              localStorage.clear();
              this.id = null;
              this.userId = null;
              this.userRole = null;
            };
            return this;

            }
    )

//Auth Service Factory for login logic

       .factory('AuthService', function ($http, Session) {

               return {
                 login: function (credentials) {
                   return $http
                     .post('LOGIN_API_URL_HERE', credentials)
                     .then(function (res) {
                       Session.create('1', '1', 'Employee');
                     });

                 },
                 isAuthenticated: function () {
                   return !!Session.userId;
                 },
                 isAuthorized: function (authorizedRoles) {
                   if (!angular.isArray(authorizedRoles)) {
                     authorizedRoles = [authorizedRoles];
                   }
                   return (this.isAuthenticated() && authorizedRoles.indexOf(Session.userRole) !== -1);
                 }
               };
       })


//Controller 

     .controller('loginController', ['$scope','$location', 'AUTH_EVENTS', 'AuthService', function($scope, $location, AUTH_EVENTS, AuthService){

                if (AuthService.isAuthenticated() === false) {

                    $scope.page_heading = "App";
                    $scope.credentials = {
                        username: '',
                        password: ''
                    };
                    $scope.login = function (credentials) {

                     if(credentials.username != "" && credentials.password != ""){

                        AuthService.login(credentials).then(function () {
                            $scope.login_message = AUTH_EVENTS.loginSuccess;
                             // Path After login        
                             $location.path("/");
                              }, function () {
                            $scope.login_message = AUTH_EVENTS.loginFailed;

                              });

                     }else{
                        $scope.login_message =  credentials.username == "" ? 'Username Required' :  $scope.login_message;
                        $scope.login_message =  credentials.password == "" ? 'Password Required' :  $scope.login_message;
                        $scope.login_message =  credentials.username == "" && credentials.password == "" ? 'Username & Password Required' : $scope.login_message;
                     }
                    };
                }else{
                               // Path After login
                    $location.path("/");
                }
            }]);

登录后,您可以在任何地方查看此类会议

if (localStorage.getItem('sessionId') != "")
       // Check for session in localstorage used in case of  single time login
    Session.setSession(localStorage.getItem('sessionId'),localStorage.getItem('userId'), localStorage.getItem('userRole'));

if (AuthService.isAuthenticated()){

   // Redirect to Dashboard
}else{

  //Redirect to Login
}