2013-05-15 15 views
70

Quando l'unità esegue il test su una fabbrica angolare (con Karma + Jasmine), come faccio a iniettare una dipendenza da stub nella fabbrica sottoposta a test?Unit test AngularJS factory che hanno dipendenze

Ecco la mia fabbrica:

mod = angular.module('myFactoryMod', []); 

mod.factory('myFactory', [ 
    '$log', 'oneOfMyOtherServices', function($log, svc) { 
    return makeSomethingThatDoesSomethingWithTheseDependencies($log, svc); 
    } 
]); 

oneOfMyOtherServices è necessario quando si crea un'istanza mia fabbrica.

Ecco la mia prova:

it('can get an instance of my factory', function() { 
    var oneOfMyOtherServicesStub; 

    angular.mock.module('myFactoryMod'); 

    oneOfMyOtherServicesStub = { 
    someVariable: 1 
    }; 

    //****How do I get my stub in my target? **** 

    angular.mock.inject(['myFactory', function(target) { 

     expect(target).toBeDefined(); 

    } 
    ]); 
}) 

N.B. So che $controller permette questo per i controller, ma non vedo un equivalente per le fabbriche.

risposta

85

Ci sono due modi per ottenere qualcosa di simile, che io sappia:

  1. Usa $provide e un modulo anonimo per iniettare il mock.
  2. Inietta il servizio che ti piacerebbe prendere in giro e usa la capacità di spionaggio di jasmine per fornire valori simulati.

La seconda opzione funziona solo se si conoscono esattamente i metodi con cui il codice in prova chiamerà il servizio inserito e si possono facilmente prendere in giro. Poiché sembra che tu stia accedendo a una proprietà di dati sul servizio (piuttosto che a un metodo), la ricerca della prima opzione potrebbe essere la soluzione migliore.

Utilizzando $provide sarebbe grosso modo simile a questa:

describe('myFactory', function() { 
    // Load your module. 
    beforeEach(module('myFactoryMod')); 

    // Setup the mock service in an anonymous module. 
    beforeEach(module(function ($provide) { 
    $provide.value('oneOfMyOtherServicesStub', { 
     someVariable: 1 
    }); 
    })); 

    it('can get an instance of my factory', inject(function(myFactory) { 
    expect(myFactory).toBeDefined(); 
    })); 
}); 
+0

Sì, penso che la scelta 1 sia la strada da percorrere. Grazie! –

+6

Mi piacerebbe iniettare myFactory in tutti i test. Può essere fatto prima? Ho provato ma non ha funzionato ... –

+10

Grazie per questa risposta +1. Sarebbe bello aggiungere un esempio di codice anche per l'opzione n. 2, per completezza. – klode

8

Il commento di @bentsai è in realtà molto utile per i servizi di test; per completezza sto aggiungendo un esempio.

Ecco un test per jasmine che fa approssimativamente quello che stai cercando. Nota: questo richiede che sia incluso angular-mocks (questo è ciò che fornisce funzioni come module e inject).

describe('app: myApp', function() { 
    beforeEach(module('myApp')); 
    var $controller; 
    beforeEach(inject(function(_$controller_) { 
    $controller = _$controller_; 
    })); 
    // Factory of interest is called MyFactory 
    describe('factory: MyFactory', function() { 
    var factory = null; 
    beforeEach(inject(function(MyFactory) { 
     factory = MyFactory; 
    })) 
    it('Should define methods', function() { 
     expect(factory.beAwesome).toBeDefined() 
     expect(factory.beAwesome).toEqual(jasmine.any(Function)) 
    }); 
    }); 
}); 

Questo è uno stub per ciò che il modulo e la definizione fabbrica associati potrebbero apparire come:

var app = angular.module('myApp', []); 
app.factory('MyFactory', function() { 
    var factory = {}; 
    factory.beAwesome = function() { 
    return 'Awesome!'; 
    } 
    return factory; 
}); 

In questo caso, è evidente l'uso di inject() permette di tirare in dipendenze, così come ti aspetteresti nella tua normale applicazione angolare e, in quanto tale, puoi creare requisiti per supportare test su cose che si basano su di essi.

+2

Ti sei perso la parte in cui inietti una dipendenza da stub a MyFactory durante i test. – skolsuper

+0

dov'è la seconda dipendenza? – Choco