将 mockService 注入到从指令初始化的控制器中
Inject mockService into an controller initialized from a directive
我想对一个指令进行单元测试 (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}
) 时,一切正常。我在这里做错了什么?
模拟控制器依赖项适用于涉及 $controller
.
的仅控制器规范
el.controller
是 getter 方法并且 has only 1 parameter:
controller(name) - retrieves the controller of the current element or
its parent.
此刻
//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")) };
});
}));
我想对一个指令进行单元测试 (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}
) 时,一切正常。我在这里做错了什么?
模拟控制器依赖项适用于涉及 $controller
.
el.controller
是 getter 方法并且 has only 1 parameter:
controller(name) - retrieves the controller of the current element or its parent.
此刻
//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")) };
});
}));