使用指令控制器来处理与路由相关的逻辑($state
/$route
)始终是一个好主意,这是控制器的工作,而不是链接功能的工作。
如果指令可以通过测试其控制器并模拟其本地依赖项来完全测试(归功于 JB Nizet 的回答)故事就这样结束了:
$controller('...', { $scope: scope, $stateParams: { ... });
常规指令规范并非如此$compile
. $compile
uses $controller
在内部实例化控制器,但不接受局部变量来模拟其依赖项。
有几种方法可以处理这个问题。
$provide.factory
If $stateParams
不必直接注入到spec中,因此是未实例化的,它的值可以在模块引导后定义。当每个规范只应模拟一次服务实例值时,无需再犹豫:
var stateParams;
beforeEach(module(('...', function ($provide) {
$provide.factory('$stateParams', function () {
return stateParams;
});
}));
it('...', inject(function ($compile) {
stateParams = { ... };
...
$provide.constant
$provide
服务提供者可以作为服务实例公开 https://stackoverflow.com/a/33704523/3731501在模块引导后(重新)定义服务:
beforeEach(module('...', function ($provide) {
$provide.value('$provide', $provide);
}));
it('...', inject(function ($provide, $compile) {
$provide.constant('$stateParams', { ... });
...
$provide.constant
在这种情况下更可取,因为它将替换缓存$stateParams
服务实例(如果之前已注入),而$provide.value
won't.
角度复制
angular.copy
(实际上 UI Router 0.x 使用它来保持$stateParams
object up to date)可用于保留现有对象引用但替换其内容:
it('...', inject(function ($stateParams, $compile) {
angular.copy({ ... }, $stateParams);
...
$state.params
$state
服务还鲜为人知公开暴露给API http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.%24state#properties_params财产params
,它可以用来替代$stateParams
为整个代码提供服务以提高其可测试性。
$stateParams
and $state.params
可能不指同一个对象,因此必须选择其中之一。
以因未经请求而导致测试脆弱的风险为代价$state
注入,它可以像
it('...', inject(function ($state, $compile) {
$state.params = { ... };
...