将mockService注入从指令初始化的控制器中

时间:2016-04-26 13:54:18

标签: angularjs unit-testing karma-runner karma-jasmine

我希望单元测试(karma)一个指令,它有一个带有注入服务的控制器。

请参阅以下代码:

angular
    .module('webkr')
    .directive('userChangePassword', userChangePassword)
    .directive('compareTo', compareTo);


  /** @ngInject */
  function userChangePassword() {
    var directive = {
      restrict: 'E',
      scope: {},
      templateUrl: 'app/components/account/user_change_password/user_change_password.html',
      controller: changePasswordController,
      controllerAs: 'vm',
      bindToController: true
    };

    return directive;

    /** @ngInject */
    function changePasswordController($log, User, toastr) {
      var _this = this;

      //properties
      _this.formModel = {
        password: null,
        oldPassword: null,
        passwordRepetition: null
      };
      _this.formDefinition = {
        oldPassword: {
          name: 'oldPassword',
          label: 'Altes Passwort',
          placeholder: 'Altes Passwort',
          error: 'old password is required.'
        },
        password: {
          name: 'password',
          label: 'Neues Passwort',
          placeholder: 'Neues Passwort',
          error: 'new password is required.'
        },
        passwordRepetition: {
          name: 'passwordRepetition',
          label: 'Passwort bestätigen',
          placeholder: 'Passwort bestätigen',
          errorRequired: 'old password is required.',
          errorInvalid: 'Confirmation password is not equal new password.'
        }
      };

      //methods

      /**
       * cancel change password procedure
       */
      _this.cancelChangePassword = function () {
        //clean form data

        _this.changePasswordForm.$setPristine();
      };
      /**
       * submit change password
       */
      _this.submitPasswordChange = function () {
        if (_this.changePasswordForm.$invalid) {
          return;
        }

        User.changePassword(_this.formModel).then(function () {
          toastr.info('Password changed', JSON.stringify(_this.formModel));
          _this.cancelChangePassword();
        }, function (err) {
          toastr.error('Can`t change password');
          $log.error(err);
        });
      };
    }
  }

我的单元测试相应:

(function () {
  'use strict';

  describe('directive user_change_password', function () {
    var el, compile, rootScope, controller, mockUserService;

    beforeEach(function () {
      mockUserService = jasmine.createSpyObj('User', ['changePassword'])
      module('webkr', 'ngMockE2E')
    });

    beforeEach(inject(function ($compile, $rootScope, $controller, $q, $log, toastr) {
      compile = $compile;
      rootScope = $rootScope;

      //Service routes used in controller
      mockUserService.changePassword.and.returnValue($q.when("result"));

      //Compile element
      el = compile("<user-change-password></user-change-password>")(rootScope);
      rootScope.$digest();

      //Init controller
      controller = el.controller("userChangePassword", {
        $log: $log,
        User: mockUserService,
        toastr: toastr
      });

      //Spy on the form
      spyOn(controller.changePasswordForm, '$setPristine')

    }));

    it('should be compiled', function () {
      expect(el.html()).not.toEqual(null);
    });
  });
})();

不知何故,控制器未正确初始化。当我删除对象({$log:$log,User:mockUserService,toastr:toastr})时,一切正常。我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

模拟控制器依赖项适用于涉及$controller的仅限控制器的规范。

el.controller是getter方法,has only 1 parameter

  

controller(name) - 检索当前元素的控制器或   它的父母。

此刻

  //Init controller
  controller = el.controller("userChangePassword", { ... });

编译指令并对其控制器进行实例化,这就是为什么可以检索它的实例。

当测试指令控制器坚持在注射器级别进行模拟时,模拟服务:

beforeEach(module('webkr', 'ngMockE2E', function ($provide) {
  $provide.factory('User', function ($q) {
     return { changePassword: jasmine.createSpy().and.returnValue($q.when("result")) };
  });      
}));