How can i test a AngularJS provider?

后端 未结 3 1062
孤城傲影
孤城傲影 2021-02-03 12:09

I need to test my own angular provider, and I need to test it in both config and run phase to check that config methods work and that the instantiated provider is indeed configu

相关标签:
3条回答
  • 2021-02-03 12:35

    Just in case you'd like to have a minification-proof version of your provider, things become slightly more complicated.

    Here is the provider code:

    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;
            }];
        }]);
    

    The test case:

    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);
        });
    });
    

    In this case $get is an array and you can't just call it as a usual function providing dependencies as arguments. The solution is to use $injector.invoke().

    That's strange that most tutorials and samples miss this detail.

    0 讨论(0)
  • 2021-02-03 12:39

    here is a little helper that properly encapsulates fetching providers, hence securing isolation between individual tests:

      /**
       * @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
      }
    
    • the process of fetching the provider is fully encapsulated: no need for closure variables that compromise isolation between tests.
    • the process can be split in two steps, a 'module' step and an 'inject' step, which can be appropriately grouped with other calls to 'module' and 'inject' within a unit test.
    • if splitting is not required, retrieving a provider can simply be done in a single command!
    0 讨论(0)
  • It's actually a lot simpler than it would at first seem to test a provider in 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();
      }));
    });
    

    ```

    The proof is in the Plunker: http://plnkr.co/edit/UkltiSG8sW7ICb9YBZSH

    0 讨论(0)
提交回复
热议问题