首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在AngularJS中对隔离范围指令进行单元测试

如何在AngularJS中对隔离范围指令进行单元测试
EN

Stack Overflow用户
提问于 2013-06-29 03:01:48
回答 4查看 38.6K关注 0票数 81

在AngularJS中对隔离范围进行单元测试的好方法是什么

JSFiddle showing unit test

指令代码段

代码语言:javascript
复制
    scope: {name: '=myGreet'},
    link: function (scope, element, attrs) {
        //show the initial state
        greet(element, scope[attrs.myGreet]);

        //listen for changes in the model
        scope.$watch(attrs.myGreet, function (name) {
            greet(element, name);
        });
    }

我想要确保指令正在侦听更改-这不是与独立作用域一起工作:

代码语言:javascript
复制
    it('should watch for changes in the model', function () {
        var elm;
        //arrange
        spyOn(scope, '$watch');
        //act
        elm = compile(validHTML)(scope);
        //assert
        expect(scope.$watch.callCount).toBe(1);
        expect(scope.$watch).toHaveBeenCalledWith('name', jasmine.any(Function));
    });

更新:我通过检查预期的观察器是否被添加到子作用域来让它工作,但它非常脆弱,可能以未记录的方式使用访问器(也可以在没有通知的情况下更改!)。

代码语言:javascript
复制
//this is super brittle, is there a better way!?
elm = compile(validHTML)(scope);
expect(elm.scope().$$watchers[0].exp).toBe('name');

更新2:正如我提到的,这是脆弱的!这个想法仍然有效,但在较新版本的AngularJS中,访问器已从scope()更改为isolateScope()

代码语言:javascript
复制
//this is STILL super brittle, is there a better way!?
elm = compile(validHTML)(scope);                       
expect(elm.isolateScope().$$watchers[0].exp).toBe('name');
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-12-01 21:32:14

参见angular element api docs。如果使用element.scope(),您将获得在指令的scope属性中定义的元素的作用域。如果你使用element.isolateScope(),你会得到整个独立的作用域。例如,如果您的指令看起来像这样:

代码语言:javascript
复制
scope : {
 myScopeThingy : '='
},
controller : function($scope){
 $scope.myIsolatedThingy = 'some value';
}

然后,在测试中调用element.scope()将返回

代码语言:javascript
复制
{ myScopeThingy : 'whatever value this is bound to' }

但是如果你调用element.isolateScope(),你会得到

代码语言:javascript
复制
{ 
  myScopeThingy : 'whatever value this is bound to', 
  myIsolatedThingy : 'some value'
}

对于angular 1.2.2或1.2.3,这是正确的,不能确切地确定。在以前的版本中,只有element.scope()。

票数 102
EN

Stack Overflow用户

发布于 2013-06-29 06:16:47

您可以执行var isolateScope = myDirectiveElement.scope()来获取隔离范围。

不过,您并不真的需要测试$watch是否被调用。这更多的是测试angularjs而不是测试你的应用。但我猜这只是问题的一个例子。

票数 11
EN

Stack Overflow用户

发布于 2014-01-30 07:27:16

将逻辑移动到单独的控制器,即:

代码语言:javascript
复制
//will get your isolate scope
function MyCtrl($scope)
{
  //non-DOM manipulating ctrl logic here
}
app.controller(MyCtrl);

function MyDirective()
{
  return {
    scope     : {},
    controller: MyCtrl,
    link      : function (scope, element, attrs)
    {
      //moved non-DOM manipulating logic to ctrl
    }
  }
}
app.directive('myDirective', MyDirective);

并像测试任何控制器一样测试后者--直接传入scope对象(有关示例,请参阅Controllers section here )。

如果需要在测试中触发$watch,请执行以下操作:

代码语言:javascript
复制
describe('MyCtrl test', function ()
{
  var $rootScope, $controller, $scope;

  beforeEach(function ()
  {
    inject(function (_$rootScope_, _$controller_)
    {
      // The injector unwraps the underscores (_) from around the parameter names when matching
      $rootScope = _$rootScope_;
      $controller = _$controller_;
    });

    $scope = $rootScope.$new({});
    $scope.foo = {x: 1}; //initial scope state as desired
    $controller(MyCtrl, {$scope: $scope}); //or by name as 'MyCtrl'
  });

  it('test scope property altered on $digest', function ()
  {
    $scope.$digest(); //trigger $watch
    expect($scope.foo.x).toEqual(1); //or whatever
  });
});
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17371836

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档