cusejuice
cusejuice

Reputation: 10691

Spyon angular service method returns Unexpected POST

I have a promise in a controller that I'm trying to test and I'm getting Error: Unexpected request: POST /v1/users.

I'm trying to spyOn the AuthService.changePassword which returns a promise and test whether it got called or not. Not sure why it's actually making the POST call...

controller

  angular.module('example')
    .controller('ChangePasswordCtrl', ['AuthService', '$state',
      function(AuthService, $state) {
        var vm = this;
        vm.submitted = false;

        vm.submit = function(valid) {
          vm.submitted = true;

          if (!valid) return false;

          AuthService.changePassword(vm.email)
            .then(function(res) {
              $state.go('reset.confirmation');
            }, function(err) {
              vm.hasError = true;
            });

        };
      }
    ]);

unit test

 describe('ChangePasswordCtrl', function() {
    var ctrl, scope, AuthService, $q, $state, deferred;

    beforeEach(module('example'));

    function _inject() {
      inject(function($controller, $rootScope, _AuthService_, _$state_, _$q_) {

        scope = $rootScope.$new();
        $state = _$state_;
        $q = _$q_;
        AuthService = _AuthService_;

        ctrl = $controller('ChangePasswordCtrl', {
          $scope: scope
        });
      });
    }

    describe('#submit', function() {
      beforeEach(function() {
        _inject();

        deferred = $q.defer();
        spyOn(AuthService, 'changePassword').and.returnValue(deferred.promise);
        spyOn($state, 'go');
      });

      describe('when email address is valid', function() {
        it('should call the changePassword method on the AuthService', function() {
          ctrl.submit(true);

          scope.$digest();

          expect(ctrl.submitted).toBe(true);
          expect(AuthService.changePassword).toHaveBeenCalled();
        });
      });
    });

  });

Upvotes: 1

Views: 119

Answers (1)

hgcummings
hgcummings

Reputation: 1073

Your spec code works for me (the real implementation of AuthService.changePassword doesn't get called): http://jsfiddle.net/7W2XB/7/

angular.module('example', [])
    .factory('AuthService', function() {
        return {
          changePassword: function() {
            throw new Error('Should not be called');
          }
        };
    })
    .controller('ChangePasswordCtrl', ['AuthService',
      function(AuthService) {
        var vm = this;
        vm.submitted = false;

        vm.submit = function(valid) {
          vm.submitted = true;

          if (!valid) return false;

          AuthService.changePassword(vm.email)
            .then(function(res) {
              $state.go('reset.confirmation');
            }, function(err) {
              vm.hasError = true;
            });

        };
      }
    ]);

describe('ChangePasswordCtrl', function() {
    var ctrl, scope, AuthService, $q, deferred;


    function _inject() {
      module('ui.router');
      module('example');
      inject(function($controller, $rootScope, _AuthService_, _$state_, _$q_) {

        scope = $rootScope.$new();
        $state = _$state_;
        $q = _$q_;
        AuthService = _AuthService_;

        ctrl = $controller('ChangePasswordCtrl', {
          $scope: scope
        });
      });
    }

    describe('#submit', function() {
      beforeEach(function() {
        _inject();

        deferred = $q.defer();
        spyOn(AuthService, 'changePassword').and.returnValue(deferred.promise);
      });

      describe('when email address is valid', function() {
        it('should call the changePassword method on the AuthService', function() {
          ctrl.submit(true);

          scope.$digest();

          expect(ctrl.submitted).toBe(true);
          expect(AuthService.changePassword).toHaveBeenCalled();
        });
      });
    });

  });

Some questions that might help make the JSFiddle more realistic to your situation: What versions of angular and Jasmine are you using? - How are you defining the AuthService (presumably using angular.factory)?

Upvotes: 1

Related Questions