कैसे यूनिट टेस्ट को अलग किया जाता है कोणीय निर्देश में कोणीयजेएस


81

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: जैसा कि मैंने उल्लेख किया है यह भंगुर है! यह विचार अभी भी काम कर रहा है लेकिन एंगुलरजेएस के नए संस्करणों में एक्सेसर निम्न से बदल गया scope()है isolateScope():

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

क्या आपको जासूसी करने का एक तरीका मिल गया?
tusharmath

@ तुषार वास्तव में नहीं, क्योंकि इससे पहले कि यह काम करने का एक तरीका है, लेकिन यह बिना किसी नोटिस के परिवर्तन के अधीन है, इसलिए अपने जोखिम पर उपयोग करें।
डेनिएलम्ब

जवाबों:


102

कोणीय तत्व एपी डॉक्स देखें । यदि आप element.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 () था।


1
v1.2.3 करतब (jqLite): अलग-थलग को उजागर करें () गुंजाइश के समान
गेट्टर

1
लेकिन आप $ घड़ी विधि पर जासूसी कहाँ करते हैं?
tusharmath

1
आप $ घड़ी पर चलने वाले फ़ंक्शन को उजागर कर सकते हैं और फिर उस पर जासूसी कर सकते हैं। निर्देश में, "गुंजाइश.myfunc = function () ..." सेट करें, फिर $ घड़ी में "$ गुंजाइश। $ घड़ी ('myName', गुंजाइश.myfunc);"। अब परीक्षण में आप अलग-अलग दायरे से myFunc प्राप्त कर सकते हैं और उस पर जासूसी कर सकते हैं।
यार स्वाद

22
मेरे लिए काम नहीं करता है। element.isolateScope()लौटता है undefined। और element.scope()एक ऐसा दायरा देता है जिसमें वह सारा सामान नहीं होता जो मैंने अपने दायरे में रखा था।
mcv

4
@ mcv मैंने पाया कि मुझे element.children().isolateScope()
क्या

11

आप var isolateScope = myDirectiveElement.scope()अलग-अलग गुंजाइश पाने के लिए कर सकते हैं ।

आपको वास्तव में परीक्षण करने की आवश्यकता नहीं है कि $ घड़ी को हालांकि कहा गया था .. जो आपके ऐप के परीक्षण से अधिक परीक्षण angularjs है। लेकिन मुझे लगता है कि यह सवाल के लिए सिर्फ एक उदाहरण है।


2
मुझे यकीन नहीं है कि मैं मानता हूं कि यह "टेस्टिंग कोणीय" है, मैं यह परीक्षण नहीं कर रहा हूं कि $ वॉच काम करती है, लेकिन बस यह है कि निर्देश संपत्ति "वायर्ड-अप" कोणीय है।
डेनिएलम्ब

1
इसके अलावा daniellmb, इसका परीक्षण करने का तरीका आपके greetफ़ंक्शन और उस पर जासूसी करना होगा, और अगर यह कहा जाता है - तो $ घड़ी नहीं।
एंड्रयू जोसलिन

सही है, यह एक विरोधाभासी उदाहरण है, लेकिन अगर अलग-अलग दायरे का परीक्षण करने के लिए एक साफ तरीका है, तो मुझे दिलचस्पी थी। इनकैप्सुलेशन को तोड़ना और स्कोप को इस दायरे में लाने से काम नहीं चलेगा क्योंकि इसमें जासूस को जोड़ने से पहले हुक नहीं है।
डेनिएलम्ब

@AndyJoslin, जिज्ञासा से बाहर, क्यों एक isolateScopeचर बनाने के लिए ? इस एगहेड वीडियो पर एंग की टिप्पणी देखें ( egghead.io/lessons/angularjs-unit-testing-directive-scope ): कोणीय 1.2 के रूप में, अलग-अलग दायरे को पुनः प्राप्त करने के लिए, किसी element.isolateScope()को element.scope() code.angularjs.org/1.2 के
डेंजर

1

लॉजिक को एक अलग कंट्रोलर के पास ले जाएं, यानी:

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

और बाद में परीक्षण करें जैसा कि आप किसी भी नियंत्रक - गुंजाइश ऑब्जेक्ट को सीधे पास कर रहे हैं ( उदाहरण के लिए यहां नियंत्रक अनुभाग देखें )।

अगर आपको अपने परीक्षण में $ घड़ी को ट्रिगर करने की आवश्यकता है:

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

0

मुझे यकीन नहीं है कि यह अलग-थलग गुंजाइश के साथ संभव है (हालांकि मुझे आशा है कि कोई मुझे गलत साबित करता है)। निर्देश में जो अलग-अलग गुंजाइश बनती है, वह अच्छी तरह से अलग-थलग होती है, इसलिए निर्देश में $ घड़ी विधि उस दायरे से अलग होती है जो आप यूनिट टेस्ट में जासूसी कर रहे होते हैं। यदि आप गुंजाइश बदलते हैं: {} से गुंजाइश: सच है, तो डायरेक्टिव स्कोप प्रोटोटाइपिक रूप से विरासत में मिलेगा और आपके टेस्ट पास होने चाहिए।

मुझे लगता है कि यह सबसे आदर्श समाधान नहीं है, क्योंकि कभी-कभी (बहुत समय), अलग-अलग गुंजाइश एक अच्छी बात है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.