【问题标题】:How can i test a AngularJS provider?我如何测试 AngularJS 提供者?
【发布时间】:2023-04-01 18:10:02
【问题描述】:

我需要测试我自己的 Angular 提供程序,我需要在配置和运行阶段对其进行测试,以检查配置方法是否有效,以及实例化的提供程序是否确实配置了正确的参数。

当我询问提供程序的依赖注入时,它找不到 APIResourceFactoryProvider,只有 APIResourceFactory,而且我在到目前为止查看的存储库中没有找到任何这样的示例。

【问题讨论】:

    标签: unit-testing angularjs jasmine


    【解决方案1】:

    它实际上比最初在 AngularJS 中测试提供者要简单得多:

    describe('Testing a provider', function() {
      var provider;
    
      beforeEach(module('plunker', function( myServiceProvider ) {
          provider = myServiceProvider;
      }));
    
      it('should return true on method call', inject(function () {
        expect( provider.method() ).toBeTruthy();
      }));
    });
    

    ```

    证明在 Plunker 中:http://plnkr.co/edit/UkltiSG8sW7ICb9YBZSH

    【讨论】:

    • 在不调用inject 的情况下如何工作?我发现我必须使用inject() 来关注module() 电话
    • 注入包装测试(在 it(...) 语句中)
    • "The proof is in the Plunker" 它没有用,但是抛出了很多依赖错误。
    • 使用 beforeEach(inject());在它之前('test-case')而不是在每个测试用例中都使用它('test-case', inject(function(){})
    【解决方案2】:

    以防万一您希望提供程序的缩小版本,事情会变得稍微复杂一些。

    这里是提供者代码:

    angular
        .module('core.services')
        .provider('storageService', [function () {
            function isLocalStorageEnabled(window) {
                return true;
            }
    
            this.$get = ['$window', 'chromeStorageService', 'html5StorageService',
                function($window, chromeStorageService, html5StorageService) {
                return isLocalStorageEnabled($window) ? html5StorageService : chromeStorageService;
            }];
        }]);
    

    测试用例:

    describe('Storage.Provider', function() {
        var chrome = {engine: 'chrome'};
        var html5 = {engine: 'html5'};
        var storageService, provider;
    
        beforeEach(module('core.services'));
        beforeEach(function () {
            module(function (storageServiceProvider) {
                provider = storageServiceProvider;
            });
        });
        beforeEach(angular.mock.module(function($provide) {
            $provide.value('html5StorageService', html5);
            $provide.value('chromeStorageService', chrome);
        }));
    
        // the trick is here
        beforeEach(inject(function($injector) {
            storageService = $injector.invoke(provider.$get);
        }));
    
        it('should return Html5 storage service being run in a usual browser', function () {
            expect(storageService).toBe(html5);
        });
    });
    

    在这种情况下,$get 是一个数组,您不能将它作为提供依赖项作为参数的常用函数来调用。解决方案是使用 $injector.invoke()

    奇怪的是大多数教程和示例都忽略了这个细节。

    【讨论】:

      【解决方案3】:

      这里有一个小助手,可以正确封装获取提供程序,从而确保各个测试之间的隔离:

        /**
         * @description request a provider by name.
         *   IMPORTANT NOTE: 
         *   1) this function must be called before any calls to 'inject',
         *   because it itself calls 'module'.
         *   2) the returned function must be called after any calls to 'module',
         *   because it itself calls 'inject'.
         * @param {string} moduleName
         * @param {string} providerName
         * @returns {function} that returns the requested provider by calling 'inject'
         * usage examples:
          it('fetches a Provider in a "module" step and an "inject" step', 
              function() {
            // 'module' step, no calls to 'inject' before this
            var getProvider = 
              providerGetter('module.containing.provider', 'RequestedProvider');
            // 'inject' step, no calls to 'module' after this
            var requestedProvider = getProvider();
            // done!
            expect(requestedProvider.$get).toBeDefined();
          });
         * 
          it('also fetches a Provider in a single step', function() {
            var requestedProvider = 
              providerGetter('module.containing.provider', 'RequestedProvider')();
      
            expect(requestedProvider.$get).toBeDefined();
          });
         */
        function providerGetter(moduleName, providerName) {
          var provider;
          module(moduleName, 
                 [providerName, function(Provider) { provider = Provider; }]);
          return function() { inject(); return provider; }; // inject calls the above
        }
      
      • 获取提供程序的过程被完全封装:不需要影响测试之间隔离的闭包变量。
      • 该过程可以分为两个步骤,一个“模块”步骤和一个“注入”步骤,可以与单元测试中对“模块”和“注入”的其他调用适当地分组。
      • 如果不需要拆分,只需一个命令即可检索提供程序!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-23
        • 2013-01-24
        • 2014-01-24
        相关资源
        最近更新 更多