2013-05-15 12 views
70

Kiedy testuję fabrykę Angulara (z karmą + jaśminem), w jaki sposób mogę wstrzyknąć zależność pośrednią do testowanej fabryki?Testowanie jednostek Fabryki AngularJS, które mają zależności:

Oto moja fabryka:

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

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

oneOfMyOtherServices jest potrzebne przy uruchamianiu mój fabryki.

Oto moja próba:

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

    } 
    ]); 
}) 

nb Wiem, że $controller dopuszcza to dla kontrolerów, ale nie widzę odpowiednika dla fabryk.

Odpowiedz

85

Istnieją dwa sposoby, aby osiągnąć coś takiego, że wiem od:

  1. Korzystając $provide i anonimowy moduł wstrzyknąć makiety.
  2. Wstrzyknij usługę, którą chcesz kpić i użyj umiejętności szpiegowskich jaśminu, aby dostarczyć fałszywych wartości.

Druga opcja działa tylko wtedy, gdy dokładnie wiesz, jakie metody testowany kod będzie wywoływał w usłudze, którą można wstrzyknąć, i możesz z łatwością je wyśmiewać. Ponieważ wydaje się, że uzyskujesz dostęp do właściwości danych w usłudze (a nie w metodzie), najlepiej jest zastosować pierwszą opcję.

Korzystanie $provide byłoby z grubsza wygląda tak:

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

Tak, myślę, że wybór 1 jest drogą. Dzięki! –

+6

Chciałbym wstrzyknąć myFactory do wszystkich testów. Czy można to zrobić w beforeEach? Próbowałem, ale to nie zadziałało ... –

+10

Dzięki za tę odpowiedź +1. Byłoby miło dodać przykład kodu również dla opcji # 2, dla kompletności. – klode

8

Komentarz przez @bentsai jest rzeczywiście bardzo pomocne dla usług badawczych; dla kompletności dodaję przykład.

Oto test dla jasmine, który zawiera mniej więcej to, czego szukasz. Uwaga: wymaga to dołączenia angular-mocks (zapewnia funkcje takie jak module i 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)) 
    }); 
    }); 
}); 

To jest tylko zalążek tego, co moduł i powiązany definicja fabryka mogłaby wyglądać następująco:

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

W tym przypadku oczywiste jest zastosowanie inject() pozwala ciągnąć w zależności, jak można się spodziewać w normalnym, kanciastym zastosowaniu - i jako takie można tworzyć wymagania, aby wspierać testowanie rzeczy, które na nich polegają.

+2

Brakowało części, w której wstrzyknięto zależność kodu pośredniczącego do MyFactory w testowaniu. – skolsuper

+0

Gdzie jest druga zależność? – Choco