我有以下Angular控制器:
angular.module('dashboard')
.controller('DashboardCtrl', ['$rootScope', '$scope', '$interval', 'domainService', 'messageService', 'currentUserAccount', 'unreadMessagesCount', 'latestMessages', function ($rootScope, $scope, $interval, domainService, messageService, currentUserAccount, unreadMessagesCount, latestMessages) {
$scope.$on('useraccount:updated', function () {
domainService.currentUserAccount().success(function (data) {
$scope.currentUserAccount = data;
});
});
...
它有许多依赖项。
我只是想测试一下这个控制器确实在currentUserAccount
上设置了$scope
。
我有以下Angular测试 - 工作正常:
describe('DashboardCtrl', function () {
var scope, httpBackend;
beforeEach(module('bignibou', 'dashboard'));
beforeEach(inject(function ($controller, $rootScope, domainService, messageService, $httpBackend) {
scope = $rootScope.$new();
$controller('DashboardCtrl', {
$scope: scope,
domainService: domainService,
messageService: messageService,
currentUserAccount: {data: {firstName: 'John'}},
unreadMessagesCount: 0,
latestMessages: []
});
httpBackend = $httpBackend;
//TODO: do I need all those expectations?
httpBackend.whenGET('/api/utils/signup-roles').respond({});
httpBackend.whenGET('/api/utils/parents-needs').respond({});
httpBackend.whenGET('/api/utils/childcare-worker-types').respond({});
httpBackend.whenGET('/api/utils/childcare-types').respond({});
httpBackend.whenGET('/api/utils/all-day-to-time-slots').respond({});
httpBackend.whenGET('/api/utils/regular-day-to-time-slots').respond({});
httpBackend.whenGET('/info').respond({build: {version: '1.0'}});
httpBackend.whenGET(/app.+/).respond({});
httpBackend.whenGET('/api/utils/current-useraccount').respond({id: 42, firstName: 'Pedro'});
}));
it('should handle user account updated', function () {
scope.$emit('useraccount:updated');
httpBackend.flush();
expect(scope.currentUserAccount.firstName).toEqual('Pedro');
});
});
然而,我对此并不满意,因为它有很多依赖性 - 更糟糕的是,未满/期望/要求变得笨拙。
原因是我依赖顶级模块 - 上面导入为bignibou
......
以下是该模块的声明:
angular.module('bignibou', [
'ngResource', 'ngMessages', 'ngCookies', 'ngAnimate', 'ngTouch', 'ngSanitize',
'ui.router', 'ui.utils', 'ui.bootstrap', 'pascalprecht.translate', 'angularMoment', 'checklist-model', 'ngTagsInput', 'angular-loading-bar', 'cfp.loadingBar',
'home', 'signup', 'signin', 'signout', 'navbar', 'dashboard', 'useraccount', 'advertisement', 'search', 'geolocation', 'utils', 'message'
]);
angular.module('home', []);
angular.module('signup', []);
angular.module('signin', []);
angular.module('signout', []);
angular.module('navbar', []);
angular.module('dashboard', []);
angular.module('useraccount', []);
angular.module('advertisement', []);
angular.module('search', []);
angular.module('geolocation', []);
angular.module('message', []);
angular.module('utils', []);
然后在utils
模块中,我有多个$http
来电:
.run(['$rootScope', 'domainService', function ($rootScope, domainService) {
domainService.signupRoles().then(function (param) {
$rootScope.signupRoles = param.data;
});
domainService.parentsNeeds().then(function (param) {
$rootScope.parentsNeeds = param.data;
});
domainService.childcareWorkerTypes().then(function (param) {
$rootScope.childcareWorkerTypes = param.data;
});
domainService.childcareTypes().then(function (param) {
$rootScope.childcareTypes = param.data;
});
domainService.allDayToTimeSlots().then(function (param) {
$rootScope.allDayToTimeSlots = param.data;
});
domainService.regularDayToTimeSlots().then(function (param) {
$rootScope.regularDayToTimeSlots = param.data;
});
}])
现在我如何重新设计/重构我的测试,以便我可以避免所有$http
来电期望?
换句话说,我正在测试DashboardCtrl
依赖domainService
模块中的utils
依赖项,$http
模块本身会进行多次{{1}}次调用。
这迫使我必须在我的测试中设置许多期望,导致笨拙的测试代码......
有人可以建议解决这个问题吗?我错过了什么?这是测试设计问题还是应用程序设计问题?
答案 0 :(得分:0)
用户JB Nizet建议我重新安排我的依赖项,从而使我走上正轨。
使用这个漂亮的工具http://angularjs-graph.org/或github,我能够可视化我的角度依赖图并重新排列依赖关系,从而避免在我的测试中加载所有依赖项。
我的测试现在更加简洁,我避免了不必要的期望:
describe('DashboardCtrl', function () {
var $scope, $httpBackend;
beforeEach(module('dashboard', 'utils', 'message'));
beforeEach(inject(function ($controller, $rootScope, domainService, messageService, _$httpBackend_) {
$scope = $rootScope.$new();
$controller('DashboardCtrl', {
$scope: $scope,
domainService: domainService,
messageService: messageService,
currentUserAccount: {data: {firstName: 'John'}},
unreadMessagesCount: 0,
latestMessages: []
});
$httpBackend = _$httpBackend_;
$httpBackend.whenGET('/api/utils/current-useraccount').respond({id: 42, firstName: 'Pedro'});
}));
it('should handle user account updated', function () {
$scope.$emit('useraccount:updated');
$httpBackend.flush();
expect($scope.currentUserAccount.firstName).toEqual('Pedro');
});
});
我可以看到我不再拉出顶级bignibou
(我的应用名称)模块,然后我选择性地使用所需的模块。