2013-04-13 45 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); 
});