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

Unit test controller with injected service

我想测试我的注入服务是否在我的控制器中被调用。

login.controller.js

angular.module('exampleModule')
  .controller('LoginCtrl', ['$state', 'AuthService',
    function($state, AuthService) {
      var self = this;

      self.submit = function() {
        AuthService.login(self.credentials)
          .then(function(res) {
            console.log('success');
            $state.go('home');
          }, function(res) {
            if (res.status === 400) {
              console.log('error')
            } 
          });
      };
    }
  ]);

login.service.js

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

      authService.login = function(credentials) {
        return $http.post('/api/authenticate', credentials);
          .then(function(res) {
            return res;
          });
      };

      return authService;
    }
  ]);

login.controller.test.js

describe('Controller: LoginCtrl', function() {
  beforeEach(module('exampleModule'));

  var ctrl, authService;

  beforeEach(inject(function($controller, AuthService){
    ctrl = $controller('LoginCtrl');
    authService = AuthService;
  }));


  describe('submit function', function() {
    beforeEach(function(){
      ctrl.submit();
    });

    it('should call AuthService', function() {
      expect(authService.login).toHaveBeenCalled();
    });    
  });

});

如何正确测试 AuthService.login 是否被调用?通过我将 AuthService 注入测试的方式,我遇到了这些错误:

TypeError: 'undefined' is not an object (evaluating 'AuthService.login(self.credentials).then')

您需要模拟 login() 方法并使其成为 return 承诺:

describe('Controller: LoginCtrl', function() {
  beforeEach(module('exampleModule'));

  var ctrl, authService, $q;

  beforeEach(inject(function($controller, _$q_, AuthService){
    ctrl = $controller('LoginCtrl');
    $q = _$q_;
    authService = AuthService;
  }));


  describe('submit function', function() {
    beforeEach(function(){
      var deferred = $q.defer();
      spyOn(authService, 'login').and.returnValue(deferred.promise);
      ctrl.submit();
    });

    it('should call AuthService', function() {     
      expect(authService.login).toHaveBeenCalled();
    });    
  });
});

Working Plunker