2013-03-13 23 views
10

Ho bisogno di testare il mio provider angolare, e ho bisogno di testarlo sia in configurazione che in fase di esecuzione per verificare che i metodi di configurazione funzionino e che il provider istanziato sia effettivamente configurato con i parametri corretti.Come posso testare un provider AngularJS?

Quando chiedo un'iniezione di dipendenza per il provider, non è possibile trovare APIResourceFactoryProvider, solo APIResourceFactory e non ho trovato alcun esempio di ciò sui repository che ho visto finora.

risposta

20

In realtà è molto più semplice di quanto lo sarebbe in un primo momento sembrano provare un fornitore 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(); 
    })); 
}); 

`` `

La prova è nel Plunker: http://plnkr.co/edit/UkltiSG8sW7ICb9YBZSH

+0

Come funziona senza chiamate per "iniettare"? Ho scoperto che dovevo seguire la chiamata 'module()' con 'inject()' – Merott

+0

L'iniettore avvolge il test (nella dichiarazione it (...)) –

+0

"La prova è nel Plunker" Non ha funzionato lavoro, ma ha gettato molti errori di dipendenza. – LeeGee

0

qui è un piccolo aiuto che incapsula correttamente i provider di recupero, assicurando quindi l'isolamento tra i singoli test:

/** 
    * @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 
    } 
  • il processo di recupero del provider è completamente incapsulato: nessuna necessità di variabili di chiusura che compromettono l'isolamento tra i test.
  • il processo può essere suddiviso in due passaggi, un passaggio di "modulo" e un passaggio di "iniezione", che possono essere raggruppati in modo appropriato con altre chiamate a "modulo" e "iniettare" all'interno di un test di unità.
  • se la suddivisione non è richiesta, il recupero di un provider può essere eseguito semplicemente con un singolo comando!
1

Nel caso in cui si desideri avere una versione a prova di prova del proprio provider, le cose diventano leggermente più complicate.

ecco il codice fornitore:

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

Il banco di prova:

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 questo caso $ get è un array e non si può semplicemente chiamare come al solito una funzione che fornisce le dipendenze come argomenti. La soluzione è utilizzare $ injector.invoke().

Questo è strano che la maggior parte dei tutorial e dei campioni manca questo dettaglio.

Problemi correlati