2013-04-13 4 views
40

Wie wir hier sehen in http://docs.angularjs.org/tutorial/step_07,AngularJS Route Unit-Tests

angular.module('phonecat', []). 
    config(['$routeProvider', function($routeProvider) { 
    $routeProvider. 
     when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl}). 
     when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}). 
     otherwise({redirectTo: '/phones'}); 
}]); 

Routing-Test zu tun mit e2e Test vorgeschlagen,

it('should redirect index.html to index.html#/phones', function() { 
    browser().navigateTo('../../app/index.html'); 
    expect(browser().location().url()).toBe('/phones'); 
    }); 

Aber ich denke, die '$ routeProvider' config getan mit einer einzigen Funktion, Funktion ($ routeProvider), und wir sollten in der Lage, Test ohne Beteiligung des Browsers zu testen, da ich denke, Routing-Funktion erfordert keine Browser-DOM.

Zum Beispiel
wenn URL ist/foo muss templateUrl sein /partials/foo.html und Controller ist FooCtrl
wenn URL ist/bar, muß templateUrl sein /partials/bar.html und Controller ist BarCtrl

Es ist eine einfache Funktion IMO, und es sollte auch in einem einfachen Test, einem Komponententest getestet werden.

ich gegoogelt und für diesen $ routeProvider Unit-Test gesucht, aber kein Glück noch.

Ich denke, ich kann einen Code von hier ausleihen, konnte es aber noch nicht machen, https://github.com/angular/angular.js/blob/master/test/ng/routeSpec.js.

+0

ist keiner der 2 gut genug? – Maarten

+0

Man muss sich fragen, ob dies einen Komponententest ergeben würde, der den tatsächlichen Wert liefert; Die Konfiguration der meisten Routen entspricht genau der Konfiguration, und der Komponententest würde auf "Ist/einige/Route gleich/einige/Route?" – fwielstra

+1

@fwielstra, Ja, diese Art von Test fühlt sich an wie [zweispaltige] (http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system). Andererseits finde ich die meisten Tests so. Auf der anderen Seite finde ich Doppeleintrag nützlich. – zhon

Antwort

62

Warum nicht einfach behaupten, die Route Objekt richtig konfiguriert ist?

it('should map routes to controllers', function() { 
    module('phonecat'); 

    inject(function($route) { 

    expect($route.routes['/phones'].controller).toBe('PhoneListCtrl'); 
    expect($route.routes['/phones'].templateUrl). 
     toEqual('partials/phone-list.html'); 

    expect($route.routes['/phones/:phoneId'].templateUrl). 
     toEqual('partials/phone-detail.html'); 
    expect($route.routes['/phones/:phoneId'].controller). 
     toEqual('PhoneDetailCtrl'); 

    // otherwise redirect to 
    expect($route.routes[null].redirectTo).toEqual('/phones') 
    }); 
}); 
+1

Wenn ich versuche, den Router zu testen, ich bin immer „‚undefined‘ist kein Objekt (Bewertung‚route.routes $ [null] .redirectTo‘)“ für das letzte Szenario „erwarten ($ route.routes [null]. RedirectTo) .toEqual ('/ phones')“ – Brune

+13

Das sieht aus wie ein ziemlich nutzlos Test für mich. Nicht zu sagen, dass der von anderen vorgeschlagene Stil besser ist. –

+2

Dies wird nicht getestet, wenn basierend auf Zuständen Routen verfügbar sind/callabe. Wie behandelt dies beispielsweise den Fall "Ich bin nicht eingeloggt und versuche auf eine eingeschränkte Ressource zuzugreifen"? –

45

Ich denke, Sie sollten die $ routeProvider wie dies testen können:

angular.module('phonecat', []). 
    config(['$routeProvider', function($routeProvider) { 
    $routeProvider. 
     when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl}). 
     when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}). 
     otherwise({redirectTo: '/phones'}); 
}]); 


it('should test routeProvider', function() { 
    module('phonecat'); 

    inject(function($route, $location, $rootScope) { 

    expect($route.current).toBeUndefined(); 
    $location.path('/phones/1'); 
    $rootScope.$digest(); 

    expect($route.current.templateUrl).toBe('partials/phone-detail.html'); 
    expect($route.current.controller).toBe(PhoneDetailCtrl); 

    $location.path('/otherwise'); 
    $rootScope.$digest(); 

    expect($location.path()).toBe('/phones/'); 
    expect($route.current.templateUrl).toEqual('partials/phone-list.html'); 
    expect($route.current.controller).toBe(PhoneListCtrl); 

    }); 
}); 
+2

Das ist perfekt. '$ rootScope. $ digest()' war genau das, was ich brauchte. – marcoseu

+0

Dieser Test funktioniert nicht mehr ... – wakandan

+1

Dies funktioniert nicht, da Angular einen HttpBackend-Aufruf auslösen möchte, um das Template über Ajax abzurufen ... Lösung über diesem (von zhon) funktioniert jedoch! – alchemication

4

Die Kombination der beiden vorherigen Antworten, wenn Sie den Router als Blackbox testen möchten, die erfolgreich Routing wird, wo es sein sollte (nicht die Controller ets configs in sich selbst), was auch immer die Wege sein könnte:

// assuming the usual inject beforeEach for $route etc. 
var expected = {}; 
it('should call the right controller for /phones route', function() { 
    expected.controller = $route.routes['/phones'].controller; 
    $location.path('/phones'); 
    $rootScope.$digest(); 
    expect($route.current.controller).toBe(expected.controller); 
}); 

it('should redirect to redirectUrl from any other route', function() { 
    expected.path = $route.routes[null].redirectTo; 
    $location.path('/wherever-wrong'); 
    $rootScope.$digest(); 
    expect($location.path()).toBe(expected.path); 
});