2015-08-11 9 views
5

मेरे पास config.json फ़ाइल लोड करने के लिए एक कोणीय सेवा जिम्मेदार है। मैं इसे अपने रन चरण में कॉल करना चाहता हूं, इसलिए मैंने अपने $ rootContext में जेसन सेट किया और इसलिए, यह भविष्य में सभी के लिए उपलब्ध है।

मूलतः, यह मैं क्या मिल गया है है:

angular.module('app.core', []).run(function(CoreRun) { 
    CoreRun.run(); 
}); 

मेरे CoreRun सेवा है:

angular.module('app.core').factory('CoreRun', CoreRun); 

CoreRun.$inject = ['$rootScope', 'config']; 

function CoreRun($rootScope, config) { 
    function run() { 
    config.load().then(function(response) { 
     $rootScope.config = response.data; 
    }); 
    }  
    return { 
    run: run 
    }; 
} 

यह ठीक काम करता है और जब मैं परीक्षण यह करने की कोशिश की समस्या आ जाती है । मैं अपनी कॉन्फ़िगरेशन सेवा पर जासूसी करना चाहता हूं, इसलिए यह एक नकली वादा करता है। हालांकि, मैं इसे अपने परीक्षण के लिए कॉन्फ़िगर चरण के दौरान नहीं बना सकता, सेवाएं उपलब्ध नहीं हैं और मैं $ q इंजेक्ट नहीं कर सकता।

जहां तक ​​मैं एकमात्र मौका देख सकता हूं, मुझे कॉन्फ़िगर चरण में, मेरी कॉन्फ़िगरेशन सेवा में नकल करना है, क्योंकि इसे रन ब्लॉक द्वारा बुलाया जाता है।

एकमात्र तरीका जो मैंने पाया है वह jQuery का उपयोग करके वादा उत्पन्न कर रहा है जिसे मैं वास्तव में पसंद नहीं करता।

beforeEach(module('app.core')); 

var configSample; 

beforeEach(module(function ($provide) { 
    config = jasmine.createSpyObj('config', [ 'load' ]); 
    config.load.and.callFake(function() { 
    configSample = { baseUrl: 'someurl' };   
    return jQuery.Deferred().resolve({data: configSample}).promise(); 
    }); 
    provide.value('config', config); 
})); 

it('Should load configuration using the correspond service', function() { 
    // assert 
    expect(config.load).toHaveBeenCalled(); 
    expect($rootScope.config).toBe(configSample); 
}); 

क्या कोई और सही कामकाज करने का कोई तरीका है?

संपादित करें: शायद यह टिप्पणी करने लायक है कि यह एक मुद्दा है जब यूनिट मेरे रन ब्लॉक का परीक्षण करता है।

+1

संभावित डुप्लिकेट [$ q और $ http को .config अनुभाग में इंजेक्शन दिया जा सकता है] (http://stackoverflow.com/questions/20626514/can-q-and-http-be- इंजेक्शन -इन-द-कॉन्फ़िगर-सेक्शन) – Constantine

+0

समान लगता है लेकिन पूरी तरह से अलग है। आपके द्वारा संदर्भित एक वास्तविक मॉड्यूल के कॉन्फ़िगर चरण में $ q इंजेक्शन करने के बारे में है। यह इकाई परीक्षण के कॉन्फ़िगर चरण के दौरान रन ब्लॉक में $ q इंजेक्शन करने के बारे में है, इसलिए आप इसे अपने रन ब्लॉक का परीक्षण करने में सक्षम होने के लिए नकल कर सकते हैं। – jbernal

उत्तर

3

लगता है कि $q सही तरीके से इंजेक्ट करना संभव नहीं है, क्योंकि आपके run() में फ़ंक्शन तुरंत आग लगती है। run() ब्लॉक को कोणीय में कॉन्फ़िगर चरण माना जाता है, इसलिए inject() परीक्षण में केवल कॉन्फ़िगरेशन ब्लॉक के बाद चलता है, इसलिए यदि आप inject()$q परीक्षण में हैं, तो यह undefined होगा, क्योंकि run() पहले निष्पादित होता है।

कुछ समय बाद मैं $qmodule(function ($provide) {}) ब्लॉक में एक बहुत गंदे कामकाज के साथ प्राप्त करने में सक्षम था। विचार एक अतिरिक्त कोणीय मॉड्यूल बनाना और इसे अपने अनुप्रयोग मॉड्यूल से पहले परीक्षण में शामिल करना है। इस अतिरिक्त मॉड्यूल में run() ब्लॉक होना चाहिए, जो $q को वैश्विक नामस्थान पर प्रकाशित करने वाला है। इंजेक्टर पहले अतिरिक्त मॉड्यूल के run() और फिर ऐप मॉड्यूल के run() पर कॉल करेगा।

angular.module('global $q', []).run(function ($q) { 
    window.$q = $q; 
}); 

describe('test', function() { 

    beforeEach(function() { 

     module('global $q'); 

     module('app.core'); 

     module(function ($provide) { 
      console.log(window.$q); // exists 
     }); 

     inject(); 

    }); 
}); 

यह अतिरिक्त मॉड्यूल spec फ़ाइलों से पहले परीक्षण सूट के लिए एक अलग फ़ाइल के रूप में शामिल किया जा सकता है। यदि आप मॉड्यूल को उसी फ़ाइल में रखते हैं जहां परीक्षण हैं, तो आपको ईवेंट को वैश्विक window चर का उपयोग करने की आवश्यकता नहीं है, लेकिन फ़ाइल के भीतर केवल एक चर है।

Here is a working plunker (एक "script.js" फ़ाइल देखें)

पहले समाधान (इस मुद्दे को हल नहीं करता है):

आप वास्तव में इस मामले में $q उपयोग कर सकते हैं, लेकिन आप इसे इंजेक्षन करने के लिए है एक परीक्षण फ़ाइल के लिए। यहां, आप परीक्षण के तहत एक इकाई को वास्तव में इंजेक्ट नहीं करेंगे, लेकिन परीक्षण के अंदर इसका उपयोग करने में सक्षम होने के लिए सीधे एक परीक्षण फ़ाइल में।तो यह वास्तव में परीक्षण के अंतर्गत एक इकाई के प्रकार पर निर्भर नहीं करता है:

// variable that holds injected $q service 
var $q; 

beforeEach(module(function ($provide) { 
    config = jasmine.createSpyObj('config', [ 'load' ]); 

    config.load.and.callFake(function() { 
     var configSample = { baseUrl: 'someurl' }; 

     // create new deferred obj 
     var deferred = $q.defer(); 

     // resolve promise 
     deferred.resolve({ data: configSample }); 

     // return promise 
     return deferred.promise; 
    }); 

    provide.value('config', config); 
})); 

// inject $q service and save it to global (for spec) variable 
// to be able to access it from mocks 
beforeEach(inject(function (_$q_) { 
    $q = _$q_; 
})); 

संसाधन:

और एक और नोट : कॉन्फ़िगरेशन चरण और रन चरण दो अलग-अलग चीजें हैं। कॉन्फ़िगर ब्लॉक केवल प्रदाताओं का उपयोग करने की अनुमति देता है, लेकिन रन ब्लॉक में आप बहुत अधिक सब कुछ इंजेक्ट कर सकते हैं (प्रदाताओं को छोड़कर)। यहां अधिक जानकारी - Module Loading & Dependencies

+0

हां, ज़ाहिर है। मैं उनके बीच मतभेदों को जानता हूं। मैं बस यह उल्लेख करना चाहता था कि मुझे आदर्श रूप से मेरे परीक्षण के अंदर कॉन्फ़िगर चरण में $ q इंजेक्ट करने की आवश्यकता होगी क्योंकि यह मेरे रन ब्लॉक से पहले चलता है। – jbernal

+0

आपके उत्तर के लिए धन्यवाद। जितनी जल्दी हो सके मैं इसे कोशिश करूंगा। हालांकि, मैं पहले से ही इसका परीक्षण करना याद रखना चाहता हूं और यह काम नहीं करता है क्योंकि मेरा रन ब्लॉक पहले से ही निष्पादित हो जाने पर दूसरा _beforeach_ निष्पादित किया गया है और इसलिए, उस समय $ q को अपरिभाषित किया गया था। – jbernal

+0

दरअसल, यह काम नहीं करता है। ऐसा इसलिए हो सकता है क्योंकि जब मेरा रन ब्लॉक निष्पादित होता है तो मुझे इंजेक्शन देने के लिए '$ q' की आवश्यकता होती है ('पहले से पहले (मॉड्यूल (' app.core ')) ट्रिगर करें;') और उस पल में, पहले से पहले (इंजेक्ट (फ़ंक्शन (_ $ q_) 'अभी तक नहीं हुआ। – jbernal

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