指令中的angular + jasmine + mock $ stateParams

时间:2016-03-09 18:22:38

标签: angularjs unit-testing angularjs-directive jasmine

在指令中模拟$ stateParams的最佳方法是什么? $ stateParam成员将根据测试进行更改。

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

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

await

1 个答案:

答案 0 :(得分:5)

使用指令控制器来处理与路由相关的逻辑($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路由器0.x用来保持$stateParams对象为最新版本)可用于保留现有对象引用但替换其内容:

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

$ state.params

$state服务鲜为人知的publicly exposed to API属性params,它可以用作代码中$stateParams服务的替代品,以提高其可测试性。< / p>

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

以未经请求的$state注射引起的测试脆弱性为代价,它可以像

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