2013-06-26 5 views
5

Sono un programmatore alle prime armi, che è molto nuovo sia per AngularJS che per la pratica dei test delle unità. Ho passato ore a cercare di trovare la soluzione, ma mi sento sempre più confuso. Se qualcuno potesse indicarmi la giusta direzione lo apprezzerei molto. Cercherò di essere il più descrittivo possibile.Unità Karma/Jasmine Test di un servizio AngularJS con dipendenze

La situazione è questa:

ho creato un servizio in AngularJS (Service A), che ha un paio di funzioni. Ognuna di queste funzioni effettua una richiesta GET $ http a un'API REST e restituisce un oggetto promessa $ http che contiene dati JSON. All'interno di queste funzioni, l'URL viene costruito attraverso l'implementazione di un altro servizio molto semplice (servizio B) che è stato iniettato come dipendenza nel servizio A. Ho creato una simulazione di servizio B per isolarlo da tutte le sue dipendenze. Entrambi questi servizi sono definiti all'interno dello stesso modulo denominato "servizi". In questo caso, non c'è un reale bisogno di questa dipendenza, ma voglio solo capire come funziona.

Utilizzando Jasmine, vorrei creare un test unitario per il servizio A per garantire che le richieste che sta apportando all'API siano costruite correttamente e possibilmente se vengono restituiti i dati JSON corretti. Allo stesso tempo, non voglio che vengano fatte delle vere e proprie chiamate API.

Questo è quello che so:

$ httpBackend finto è quello che ho bisogno di essere in grado di effettuare chiamate falsi per l'API e fornisce funzionalità di aspettarsi alcune richieste e restituire i risultati previsti.

Ho bisogno di testare il vero Servizio A e di iniettare la simulazione che ho creato del Servizio B. So che ci sono modi per farlo usando Jasmine Spies e $ provide. Ho anche visto esempi in cui viene utilizzato sinon.js e non sono sicuro quale sia l'approccio migliore.


Inserirò il mio codice sorgente qui sotto, che è scritto in CoffeeScript.

Servizio A:

'use strict' 

angular.module("services") 
    .service("ServiceA", ["$http", "ServiceB", ($http, ServiceB) -> 

    #Uses underscore.js to set this default attribute 
    defaults = withCredentials:true 

    getVarset: (itemName, options={}) -> 
     options.method = "GET" 
     options.url = ServiceB.makeUrl("item/#{itemName}") 

     $http _.defaults(options, defaults) 

    getVarsets: (options = {}) -> 
     options.method = "GET" 
     options.url = ServiceB.makeUrl("items") 

     $http _.defaults(options, defaults) 

    getModelsForVarset: (itemName, options = {}) -> 
     options.method = "GET" 
     options.url = ServiceB.makeUrl("item/#{itemName}/prices") 

     $http _.defaults(options, defaults) 
    ]) 

Servizio B:

'use strict' 

angular.module('services') 
    .service 'ServiceB', [ -> 

    # Just return the string 
    # This service builds the real URL, but I've removed this 
    makeUrl: (Url) -> 
     "#{Url}" 
    ] 

risposta

4

quindi stai dicendo che si sa come fare questo con $ fornire/spie Jasmine e sono alla ricerca di alternative ? Ho usato principalmente il metodo $ fornire/spy per il mocking e per me ha funzionato molto bene finora.

qualcosa di simile:

beforeEach(function() { 

    // set up a default value for your mock 
    bMock = { 
     makeUrl: jasmine.createSpy('makeUrl() mock').andReturn('http://www....') 
    } 

    // use the $provide service to replace ServiceB 
    // with your mock 
    module('services', function($provide) { 
     $provide.value('ServiceB', bMock); 
    }); 

}); 

it('should do what its supposed to do', function() { 
    // test... 
}); 

poi, se si desidera utilizzare $ httpBackend per deridere le richieste HTTP in servizio A, è sufficiente utilizzare il servizio $ iniettore per afferrare $ httpBackend, quindi chiamare .quando (...) su di esso per impostare le cose, a la http://docs.angularjs.org/api/ngMock.$httpBackend