Angularjs 在角度测试中处理大量依赖项和$http期望

Angularjs 在角度测试中处理大量依赖项和$http期望,angularjs,Angularjs,我有以下角度控制器: angular.module('dashboard') .controller('DashboardCtrl', ['$rootScope', '$scope', '$interval', 'domainService', 'messageService', 'currentUserAccount', 'unreadMessagesCount', 'latestMessages', function ($rootScope, $scope, $in

我有以下角度控制器:

     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;
        });
    });
   ...
它有许多依赖项

我只是想测试这个控制器是否在
$scope
上设置了
currentUserAccount

我有以下角度测试-效果很好:

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
,它依赖于
utils
模块中的
domainService
依赖项,该模块本身执行许多
$http
调用

这迫使我不得不在测试中设置大量的期望值,导致测试代码笨拙


有人能提出解决这个问题的建议吗?我错过了什么?这是一个测试设计问题还是一个应用程序设计问题?

用户建议我重新安排依赖项,这并没有让我走上正轨

使用这个很好的工具或工具,我能够可视化我的角度依赖关系图并重新排列依赖关系,从而避免在测试中加载所有依赖关系

现在,我的测试更加简洁,避免了不必要的期望:

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
(我的应用程序的名称)模块,然后我有选择地使用所需的模块。

将这个run()块放在测试中不加载的模块中。我认为在我的测试中始终包含顶级模块(拉所有依赖项的模块)是最容易的在我的例子中,“bignibou”,但这似乎不是一个好主意。我猜这个问题迫使我更好地解释我的应用程序的依赖关系图。你推荐任何可以帮助我可视化依赖关系图的工具吗?这里有一个很好的工具可以帮助可视化某个应用程序的依赖关系图: