2013-04-13 44 views
40

正如我們在這裏看到的http://docs.angularjs.org/tutorial/step_07,建議angularjs路線的單元測試

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 redirect index.html to index.html#/phones', function() { 
    browser().navigateTo('../../app/index.html'); 
    expect(browser().location().url()).toBe('/phones'); 
    }); 

不過,我認爲「$ routeProvider」配置是完成一個函數,函數($ routeProvider),並且我們應該能夠在沒有瀏覽器參與的情況下進行單元測試,因爲我認爲路由功能不需要瀏覽器DOM。

例如,
當URL是/ foo,templateUrl必須/partials/foo.html和控制器是FooCtrl
當URL是/巴,templateUrl必須/partials/bar.html和控制器是BarCtrl

這是一個簡單的函數IMO,它也應該在一個簡單的測試,單元測試中測試。

我使用Google搜索和搜索此$ routeProvider單元測試,但沒有運氣。

我想我可以從這裏借一些代碼,但是還沒有成功,https://github.com/angular/angular.js/blob/master/test/ng/routeSpec.js

+0

既不夠好? – Maarten

+0

但是,人們不得不懷疑這是否會產生提供實際價值的單元測試;大多數路由配置就是這樣,配置和單元測試會歸結爲'是/某些/路由等於/某些/路由?' – fwielstra

+1

@fwielstra,是的,這種測試感覺像[複式](http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system)。再次,我發現大多數測試都是這樣。另一方面,我覺得複製條目很有用。 – zhon

回答

62

爲什麼不乾脆斷言路由對象的配置是否正確?

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

當我嘗試測試路由器時,我得到的''未定義'不是一個對象(評估'$ route.routes [null] .redirectTo')「最後一個場景」expect($ route.routes [null]。 redirectTo).toEqual('/ phones')「 – Brune

+13

這對我來說看起來像是一個非常無用的測試。不要說別人提出的風格更好。 –

+2

這不會測試是否基於狀態路由可用/ callabe。 例如,這是如何涵蓋「我沒有登錄並嘗試訪問受限制的資源」的情況? –

45

我認爲你應該能夠測試$ routeProvider這樣的:

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

這是完美的。 '$ rootScope。$ digest()'正是我所需要的。 – marcoseu

+0

此測試不再起作用... – wakandan

+1

這不起作用,因爲Angular希望觸發HttpBackend調用以通過Ajax檢索模板...解決方案在此之上(來自zhon)雖然工作正常! – alchemication

4

結合前兩次的答案,如果你想測試路由器作爲一個黑匣子已成功路由,它應該(而不是在自己的控制器ETS CONFIGS),無論路線可能是:

// 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); 
});