一尘不染

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

angularjs

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

JSFiddle显示单元测试

指令段

    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);
        });
    }

我想,以确保指令监听的变化-这确实 不是 工作,一个孤立的范围:

    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));
    });

更新:
我通过检查是否将预期的观察者添加到了子作用域中来使其工作,但是它非常脆弱,并且可能以未记录的方式使用访问器(也可能随时更改,恕不另行通知!)。

//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()

//this is STILL super brittle, is there a better way!?
elm = compile(validHTML)(scope);                       
expect(elm.isolateScope().$$watchers[0].exp).toBe('name');

阅读 197

收藏
2020-07-04

共1个答案

一尘不染

请参阅angular element api文档。如果使用
element.scope() ,则将获得在指令的scope属性中定义的元素范围。如果使用 element.isolateScope(),
则会获得整个隔离范围。例如,如果您的指令看起来像这样:

scope : {
 myScopeThingy : '='
},
controller : function($scope){
 $scope.myIsolatedThingy = 'some value';
}

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

{ myScopeThingy : 'whatever value this is bound to' }

但是,如果调用element.isolateScope(),您将得到

{ 
  myScopeThingy : 'whatever value this is bound to', 
  myIsolatedThingy : 'some value'
}

从角度1.2.2或1.2.3开始,这是正确的,但不确定。在以前的版本中,您只有element.scope()。

2020-07-04