2013-04-01 6 views
26

Ich muss eine Direktive testen, die einige injizierte Dienste anruft. Der folgende Codeabschnitt ist eine Beispieldirektive, die auf Ereignisse wartet und den Browser umleitet, wenn in einem angegebenen Element die Eingabetaste gedrückt wird.Wie injiziere ich einen Dienst in einem Direktiven Unit Test in AngularJS

Edit: Ich habe das Gefühl, ich könnte in E2E Testland waten?

angular.module('fooApp') 
    .directive('gotoOnEnter', ['$location', function ($location) { 

    var _linkFn = function link(scope, element, attrs) { 

     element.off('keypress').on('keypress', function(e) { 
        if(e.keyCode === 13) 
        { 
         $location.path(scope.redirectUrl); 
        } 
       }); 
    } 

    return { 
     restrict: 'A', 
     link: _linkFn 
    }; 
    }]); 

Das Problem ist, dass ich nicht herausgefunden habe, wie Dienste zu injizieren, auf sich in den Richtlinien spionieren.

Meine vorgeschlagene Lösung sieht so aus: Es funktioniert nicht, wie erwartet, weil ich es nicht geschafft habe, einen $locacion Dienst erfolgreich zu spionieren.

describe('Directive: gotoOnEnter', function() { 
    beforeEach(module('fooApp')); 

    var element; 

    it('should visit the link in scope.url when enter is pressed', inject(function ($rootScope, $compile, $location) { 

    element = angular.element('<input type="text" goto-on-enter>'); 
    element = $compile(element)($rootScope); 

    $rootScope.redirectUrl = 'http://www.google.com'; 
    $rootScope.$digest(); 

    var e = jQuery.Event('keypress'); 
    e.keyCode = 13; 
    element.trigger(e); 

    spyOn($location, 'path'); 

    expect($location.path).toHaveBeenCalledWith('http://www.google.com'); 
    })); 

Dies ergibt

Expected spy path to have been called with [ 'http://www.google.com' ] but it was never called. 
+0

Sie müssen den Spion erstellen, bevor zu navigieren versuchen. Ich glaube, wenn Sie den Aufruf von 'spyOn' an den Anfang der Funktion verschieben, wird es wie gewünscht funktionieren. –

Antwort

35

dekorieren, Stummel, spottet bieten oder einen anderen Dienst außer Kraft setzen, können Sie den $provide Service nutzen. $provide.value, $provide.decorator usw. Dokumentation here.

Dann können Sie Sachen wie dies tun:

var $location; 

beforeEach(function() { 
    module('studentportalenApp', function($provide) { 
     $provide.decorator('$location', function($delegate) { 

     $delegate.path = jasmine.createSpy(); 

     return $delegate; 
     }); 
    }); 

    inject(function(_$location_) { 
     $location = _$location_; 
    }); 

    }); 

...

it('should visit the link in scope.redirectUrl when enter is pressed', inject(function ($rootScope, $compile, $location) { 
    element = angular.element('<input type="text" goto-on-enter>'); 
    element = $compile(element)($rootScope); 

    $rootScope.redirectUrl = 'http://www.google.com'; 
    $rootScope.$digest(); 

    var e = jQuery.Event('keypress'); 
    e.keyCode = 13; 
    element.trigger(e); 

    $rootScope.$digest(); 

    expect($location.path).toHaveBeenCalledWith('http://www.google.com'); 

})); 
+0

URL zu Dokumentation hat sich geändert: https://docs.angularjs.org/api/auto/object/$provide – primavera133

+0

Wurde erneut geändert: https://docs.angularjs.org/api/auto/service/$provide –