2013-10-10 8 views
38

मैं एंगुलरजेएस यूनिट टेस्ट के लिए एक सेवा का मज़ाक उड़ा रहा हूं। मैं एक बाहर मज़ाक उड़ाया (यह उपलब्ध है की एक plunker script) के साथ 'असली' सेवा को बदलने के लिए $provide सेवा का उपयोग कर रहा:

describe('My Controller', function() { 

    var $scope; 
    var $provide; 

    beforeEach(angular.mock.module('myApp')); 

    beforeEach(angular.mock.module(function (_$provide_) { 

     $provide = _$provide_; 

    })); 

    beforeEach(angular.mock.inject(function($rootScope, $controller, $q){ 

     var mockMyService = { 
      getAll : function() { 
       var deferred = $q.defer(); 
       deferred.resolve([ 
      { itemText: "Foo" }, 
      { itemText: "Bar" } 
       ]); 

       return deferred.promise; 
      } 
     }; 

     $provide.value('myService', mockMyService); 

     $scope = $rootScope.$new(); 

     $controller('MyCtrl', { $scope: $scope }); 

     $rootScope.$apply(); 

    })); 

    it('Has two items defined', function() { 
     expect($scope.items.length).toEqual(2); 
    }); 
}); 

यह सिर्फ ठीक काम करता है। हालांकि, मुझे इस तथ्य को पसंद नहीं है कि मैं फ़ंक्शन का उपयोग केवल $provide सेवा का संदर्भ देने के लिए कर रहा हूं जिसका उपयोग नीचे angular.mock.inject फ़ंक्शन में किया जाता है। लेकिन अगर मैं $provide को angular.mock.inject फ़ंक्शन के पैरामीटर के रूप में सीधे पैरामीटर के रूप में जोड़ता हूं, तो मुझे 'अज्ञात प्रदाता' त्रुटि मिलती है।

यह मेरे लिए होता है कि मैं angular.mock.module फ़ंक्शन में सभी मॉकिंग कोड डाल सकता हूं। लेकिन फिर मुझे $q संदर्भ के साथ एक ही समस्या है, जो मुझे चाहिए क्योंकि मेरी मॉक सेवा को एक वादा वापस करना होगा।

दूसरे शब्दों में, अगर मैं angular.mock.module कार्य करने के लिए एक $q पैरामीटर जोड़ने तो मैं भी 'अज्ञात प्रदाता' त्रुटि मिलती है।

क्या इसे सरल बनाने का कोई तरीका है? जाहिर है कि मेरे पास क्या काम है लेकिन यह किसी भी तरह से बिल्कुल सही नहीं लगता है। मुझे लगता है कि मुझे समझ में कमी नहीं है कि क्यों कुछ प्रदाता inject कार्यों में उपलब्ध हैं और अन्य module फ़ंक्शंस में उपलब्ध हैं।

उत्तर

53

आप $provide का उपयोग inject फ़ंक्शन के भीतर नहीं कर सकते क्योंकि बाद वाले के लिए पूर्व रजिस्ट्रार प्रदाता।

describe('...', function() { 
    var serviceMock; 

    beforeEach(function() { 
     serviceMock = { 
      someMethod: function() { ... } 
     }; 

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

     inject(function(service) { 
      ...       
     }); 
    }); 
}); 

वास्तव में, आप भी $provide साथ यह इंजेक्शन लगाने से पहले मज़ाक उड़ाया सेवा को लागू करने की जरूरत नहीं है:

describe('...', function() { 
    beforeEach(function() { 
     module(function($provide) { 
      $provide.constant('someValue', 'foobar'); 
     }); 

     inject(function(someValue) { 
      var value = someValue; // will be 'foobar'; 
     }); 
    }); 
}); 

आप हालांकि अपने परीक्षण इस तरह से लिख सकते हैं: एक नजर डालें

beforeEach(function() { 
    serviceMock = {}; 

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

    inject(function(service) { 
     ...       
    }); 
}); 

it('tests something', function() { 
    // Arrange 
    serviceMock.someMethod = function() { ... } 

    // Act 
    // does something 

    // Assert 
    expect(...).toBe(...); 
}); 

यहां पर Plunker script है जो ऊपर से अधिकतर चित्रित करता है।

+0

यह बहुत अच्छा है और यह काम करता है ... जब तक आप वादा का उपयोग नहीं करते हैं। यहां मेरा मूल उदाहरण दिखाया गया एक प्लंक है: http://plnkr.co/edit/1Gbr1N?p=preview और यहां आपके द्वारा सुझाए गए तकनीक के साथ अपडेट किया गया एक कांटा है: http://plnkr.co/edit/ptAWcb?p = पूर्वावलोकन नकली सेवा असाइन नहीं की जा रही है; ऐसा लगता है कि कुछ समय के साथ हस्तक्षेप कर रहा है। – Holf

+0

मुझे आश्चर्य है कि मैं 'मॉड्यूल' फ़ंक्शन से '$ q' लाइब्रेरी क्यों नहीं पकड़ सकता? अगर मैं कर सकता, तो मेरे पास नकली सेवा बनाने के लिए मुझे जो कुछ भी चाहिए, उसके पास मेरे पास सबकुछ होगा। – Holf

+7

@ हॉल्फ आप एक वादा का उपयोग कर सकते हैं, लेकिन आपको चीजों को थोड़ा पहले स्थानांतरित करने की आवश्यकता है। यह अद्यतन [प्लंकर स्क्रिप्ट] देखें (http://plnkr.co/edit/Fi1SQq)। –

11

यह मेरे लिए काम किया जब मैं एक सेवा है जो $q का इस्तेमाल किया और काफी साफ लगता है रैप करने के लिए किया था:

var _ServiceToTest_; 
beforeEach(function() { 
    module('module.being.tested'); 
    module(function ($provide) { 
     $provide.factory('ServiceToMock', function ($q, $rootScope) { 
      var service = ...; 
      // use $q et al to heart's content 
      return service; 
     }); 
    }); 
    inject(function (_ServiceToTest_) { 
     ServiceToTest = _ServiceToTest_; 
    }); 
}); 

it('...', function() { /* code using ServiceToTest */ }); 

चाल $provide.factory बजाय $provide.value उपयोग करने के लिए किया गया था।

संबंधित मुद्दे