测试控制器中的私有方法和sidewaffle提供的模板

Testing private methods in controllers and the provided template by sidewaffle

本文关键字:sidewaffle 有方法 控制器 测试      更新时间:2023-09-26

我一直在学习如何测试我的应用程序写在角的东西,我很困惑,因为它似乎有一些东西对彼此。我试着遵循John Papa的风格指南,所以我基本上使用Sidewaffle模板。目前看来,建议的模板和可测试性是相互矛盾的。

样式指南说有一个

activate ()

方法,它关心控制器的启动逻辑,正如你在这里看到的。然而,一般的测试指南说私人方法不应该测试。我有机会在提供的示例中测试activate()方法的结果,因为它将通过

传递

vm.avengers

变量。在他的Pluralsight视频中,他使用common. activatcontroller()方法,其中他使用

$ q.all ()

来组合承诺,以便在控制器激活阶段可以方便地调用多个函数。假设我有一个函数,它不会有结果,可以通过vm传递,例如,向WebApi发送消息,以验证用户并获得令牌,并将其设置为headers,或类似的东西。下面是一个示例(服务没有被注入,它只是一个示例):

在下面的控制器中,唯一的业务逻辑是,当控制器实例化时,activate()方法调用func1()方法,该方法调用OAuthenticationService.authenticate()方法。从测试的角度来看,是否调用服务非常重要。如何测试呢?

这是一个非常类似的问题,其中一个答案建议我应该像这样使用这个关键字:

this.activate ()

但是注释说它不能与ControllerAs语法一起工作。我遵循ControllerAs语法。

当我在验证方法上为带有spy的服务创建模拟时,测试表明我没有被调用,我认为由于该方法是私有的。

I run out of ideas…

提前感谢您的帮助!

(function () {
    'use strict';
    angular
        .module('app')
        .controller('controller', controller);
    controller.$inject = ['$location']; 
    function controller($location) {
        /* jshint validthis:true */
        var vm = this;
        vm.title = 'controller';
        activate();
        function activate() {
            func1();
        }
        function func1() {
            OAuthAuthenticateService.authenticate(user).then(function() {
                //setting up headers and other stuff, nothin will be part of $scope or vm;
            });
        }
    }
})();
原始代码

:

(function () {
    'use strict';
    var controllerId = 'requestAuthorizationController';
    angular
        .module('myapp')
        .controller(controllerId, requestAuthorizationController);
    requestAuthorizationController.$inject = ['$rootScope',
                                                '$scope',
                                                'requestAuthorizationService'
                                                'Restangular'];
    function requestAuthorizationController($rootScope,
                                            $scope,
                                            requestAuthorizationService
                                            Restangular) {
        /* jshint validthis:true */
        var vm = this;
//other business logic
        activate();
        function activate() {
            requestAuthorization();
        }
        function requestAuthorization() {
            vm.fired = undefined;
            requestAuthorizationService.getDummy();
        }
    }
})();

茉莉花测试:

'use strict';
describe('RequestAuthenticationController Specification', function () {
    var RestangularProviderMock,
        localStorageServiceProvider,
        $httpProvider,
        requestAuthorizationController,
        requestAuthorizationServiceMock,
        $rootScope;
    //modules
    beforeEach(function() {
        angular.module('dilib.layout', []);
        angular.module('http-auth-interceptor', []);
    });

    //providers
    beforeEach(function () {
        module('dilib', function(RestangularProvider, _localStorageServiceProvider_, _$httpProvider_, $provide) {
            RestangularProviderMock = RestangularProvider;
            localStorageServiceProvider = _localStorageServiceProvider_;
            $httpProvider = _$httpProvider_;
            $provide.service('requestAuthorizationService', function() {
                this.getDummy = jasmine.createSpy('getDummy').and.callFake(function(num) {
                });
            });
        });
    });
    //to crank up the providers
    beforeEach(inject());
    beforeEach(inject(function (_$rootScope_, _$controller_, _requestAuthorizationService_) {
        $rootScope = _$rootScope_;
        requestAuthorizationController = _$controller_;
        requestAuthorizationServiceMock = _requestAuthorizationService_;
    }));

     describe('requestAuthorization function', function() {
         it('RequestAuthorizationService.getDummy() is called', function() {
            $rootScope.$digest();
            expect(requestAuthorizationServiceMock.getDummy).toHaveBeenCalled();
        });
    });

});

我认为我的整个方法都是错误的。我在控制器中有太多的业务逻辑。根据本文和其他文章,我必须尽可能地减少控制器中的业务逻辑,并将其置于服务公共方法中。如果我遵循这条规则,那么就不需要私有方法了。然而,问题仍然是如何处理

activate ()

方法。这足以测试执行函数的结果,这是填充的视图模型?我想答案是肯定的。

目前,我关注的是视图模型变量是否被正确填充,并且我正在将业务逻辑重构为服务。

在我看来,编写工作但难以测试的代码比编写工作且易于测试的代码要容易得多。

这个故事的另一个方面是,我已经作为一个测试人员工作了10年,在测试的许多方面都有很好的经验。但是现在,我只是摸不着头脑,如何在可测试/测试驱动的开发方式上编写代码。:)

因此,在John Papa的风格指南中,activate()方法意味着一个抽象。如果要在构造函数方法中进行大量设置,那么将其抽象到activate()方法中。这样构造函数就干净了。我不确定在你发布的代码中有太多的价值。

附带说明,您应该只对您的单元的api,外部接口进行单元测试。对于控制器,视图中操作调用的属性和方法。