带有注入服务的单元测试控制器

Unit testing controller with injected service

对以下控制器进行单元测试的最佳方法是什么? 我无法将 AuthService 正确注入我的控制器。 我见过很多不同的方法,但我不确定最佳做法是什么 -即 mocks vs spies?

我有这样一个简单的服务:

   angular.module('users')
      .factory('AuthService', ['$http', '$window',
        function($http, $window) {
          var authService = {};

          authService.login = function(creds) {
            return $http.post('/auth', creds)
              .then(function(res) {
                $window.localStorage.exampleToken = res.data.returned_token;
                return res;
              });
          };

          authService.isLoggedIn = function() {
            if($window.localStorage.exampleToken) {
              return true;
            } else {
              return false;
            }
          };

          authService.clear = function() {
            delete $window.localStorage.exampleToken;
          };

          return authService;
        }]);

我的控制器:

   angular.module('users')
      .controller('ExampleCtrl', ['AuthService', 
        function(AuthService) {
          var vm = this;

          vm.isLoggedIn = AuthService.isLoggedIn();
        }]);

我未完成的测试:

 describe('ExampleCtrl', function() {
      beforeEach(module('users'));

      var ctrl;

      beforeEach(inject(function($controller) {
        ctrl = $controller('ExampleCtrl', {});
      }));

      describe('when logged in', function() {
        beforeEach(function() {
          // how do i mock the isLoggedIn function to 
          // return true
        });

        it('should return true', function() {
          expect(ctrl.isLoggedIn).toBe(true);
        });

      });

      describe('when not logged in', function() {
        beforeEach(function() {
          // how do i mock the isLoggedIn function to 
          // return false
        });

        it('should return false', function() {
          expect(ctrl.isLoggedIn).toBe(false);
        });

      });

    });

你只能使用JasminecallFake功能:

By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied function.

var AuthService; //so that you can have a reference within all your test file
beforeEach(function() {
     inject(function(_AuthService_) {
       AuthService = _AuthService_;
     });
     spyOn(AuthService, 'isLoggedIn').and.callFake(function() {
          return true;
     });
});