【问题标题】:angular + jasmine + mock $stateParams in a directive指令中的 angular + jasmine + mock $stateParams
【发布时间】:2016-06-24 07:11:11
【问题描述】:

在指令中模拟 $stateParams 的最佳方法是什么? $stateParam 成员会根据测试而改变。

我可以使用 $controller('ctrl', $stateParams) 在控制器中轻松模拟 $stateParams,但不知道如何修改注入指令的 $stateParams。

我已经用下面的方法装饰了 $stateParams,但只能在我创建模块时声明。正如我所提到的,$stateParam 成员将通过不同的测试多次更改。

beforeEach(angular.mock.module(function ($provide) {

    $provide.provider('$stateParams', function () {
        return {
            myStateParam: true,
            myOtherStateParam: 'some text'
        };
    });

}));

【问题讨论】:

  • 我的建议:将指令中所有与 DOM 无关的工作委托给控制器(使用 controller: 'MyDirectiveController' 传递给指令,并测试控制器。
  • 你可能是对的。无论如何,它是保持指令解耦的更好模式。我会接受你的回答。
  • 我不认为这是一个答案:只是一个好的解决方法。即使现在没有实际意义,您的问题也是有效的。但是你所拥有的很好。只需将其放入每个it,而不是将其放入beforeEach

标签: angularjs unit-testing angularjs-directive jasmine


【解决方案1】:

使用指令控制器来处理与路由相关的逻辑 ($state/$route) 总是一个好主意,这是控制器的工作,而不是链接函数。

如果一个指令可以通过测试其控制器并模拟其本地依赖项来完全测试(感谢 JB Nizet 的回答),故事就结束了:

$controller('...', { $scope: scope, $stateParams: { ... });

$compile 的常规指令规范不是这种情况。 $compile 在内部使用 $controller 来实例化控制器,但不接受本地人来模拟其依赖项。

有几种方法可以处理这个问题。

$provide.factory

​​>

如果$stateParams 不必直接注入规范,因此未实例化,则可以在模块引导后定义其值。当每个规范只应该模拟一次服务实例值时,不要再看了:

var stateParams;

beforeEach(module(('...', function ($provide) {
    $provide.factory('$stateParams', function () {
        return stateParams;
    });
}));

it('...', inject(function ($compile) {
  stateParams = { ... };
  ...

$provide.constant

$provide 服务提供者can be exposed as service instance 在模块启动后(重新)定义服务:

beforeEach(module('...', function ($provide) {
  $provide.value('$provide', $provide);
}));

it('...', inject(function ($provide, $compile) {
  $provide.constant('$stateParams', { ... });
  ...

$provide.constant 在这种情况下更可取,因为如果之前注入,它将替换缓存的 $stateParams 服务实例,而 $provide.value 不会。

angular.copy

​​>

angular.copy(UI Router 0.x 实际上使用它来保持$stateParams 对象最新)可用于保留现有对象引用但替换其内容:

it('...', inject(function ($stateParams, $compile) {
  angular.copy({ ... }, $stateParams);
  ...

$state.params

$state 服务具有鲜为人知的publicly exposed to API 属性params,它可以在整个代码中用作$stateParams 服务的替代品,以提高其可测试性。

$stateParams$state.params 可能不指向同一个对象,因此必须选择其中一个。

以不请自来的$state 注入导致测试脆弱的风险为代价,它可以像整洁一样

it('...', inject(function ($state, $compile) {
  $state.params = { ... };
  ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    相关资源
    最近更新 更多