2013-01-09 39 views
50

मैं सेवा ए का परीक्षण कर रहा हूं, लेकिन सेवा ए सेवा बी पर निर्भर करता है (यानी सेवा बी को सेवा ए में इंजेक्शन दिया जाता है)।निर्भर सेवाओं को इंजेक्शन करते समय यूनिट परीक्षण AngularJS सेवाएं

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

describe("Sample Test Suite", function() { 

    beforeEach(function() { 

    module('moduleThatContainsServiceA'); 

    inject([ 
     'serviceA', function(service) { 
     this.service = service; 
     } 
    ]); 

    }); 

    it('can create an instance of the service', function() { 
    expect(this.service).toBeDefined(); 
    }); 
}); 

त्रुटि मैं मिलता है:

Error: Unknown provider: serviceBProvider

मैं कुछ इस तरह कैसे कर सकता है

यहां नमूने के परीक्षण है?

+0

FWIW: मैं एक ** QUnit संस्करण पूछा है ** इस सवाल [CodeReview.SE पर यहाँ] की (http://codereview.stackexchange.com/q/98519/10034)। – Jeroen

उत्तर

43

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

इस बार है MyAppMocks जैसे नए मॉड्यूल को परिभाषित करके, मॉक किए गए सेवाओं/मानों को वहां डालकर और फिर इस मॉड्यूल को निर्भरता के रूप में जोड़कर किया जाता है।

की (रेखाचित्र) प्रकार:

beforeEach(function() { 
    angular.module('MyAppMocks',[]).service('B', ...)); 
    angular.module('Test',['MyApp','MyAppMocks']); 
    ... 
+2

आपने अभी अपना जीवन बचाया है!: डी मैं खुद को किसी अन्य सेवा में एक नकली सेवा इंजेक्ट करने की कोशिश कर रहा था जो उस पर निर्भर था, लेकिन केवल परीक्षण मजाकिया संस्करण का उपयोग करेंगे, न कि इंजेक्शन सेवा। अब मेरे पास एक अलग मॉक मॉड्यूल है जो मैं ऐप मॉड्यूल के बाद लोड करता हूं जो वांछित सेवाओं को ओवरराइट करता है। एक जादू की तरह काम करता है! –

+3

थॉमस, क्या आप अपने समाधान के बारे में कुछ विवरण साझा कर सकते हैं? मेरे पास 2 मॉड्यूल हैं, उनमें से प्रत्येक में एक सेवा है, और पहले मॉड्यूल से service_1 को दूसरे मॉड्यूल में सर्विस_2 में इंजेक्शन दिया गया है। मैं service_1 के साथ एक नकली मॉड्यूल बना रहा हूं जो मूल सेवा_1 को ओवरराइट करना है। और यह ओवरराइट किया गया है, लेकिन केवल परीक्षणों में, इसलिए जब मैं सेवा_2 कहता हूं, तो यह अभी भी मूल सेवा_1 का उपयोग कर रहा है। –

+3

मैं [सेवाओं के लिए mocks जोड़ने] कैसे संभाल (https://github.com/daniellmb/angular-test-patterns/blob/master/patterns/service.md#suggested-service-unit-test-setup-) – daniellmb

20

वैलेंटीन समाधान मेरे लिए काम किया है, लेकिन वहाँ एक और विकल्प नहीं है।

beforeEach(function() { 

    angular.mock.module("moduleThatContainsServiceA", function ($provide) { 
       $provide.value('B', ...); 
      }); 
}); 

AngularJS सेवा अनुरोध निर्भरता इंजेक्शन द्वारा सेवा बी, सेवा बी के अपने नकली moduleThatContainsServiceA से सेवा बी के बजाय प्रदान की जाएगी फिर जब।

इस तरह आपको सेवा को नकल करने के लिए अतिरिक्त कोणीय मॉड्यूल बनाने की आवश्यकता नहीं है।

+0

उत्कृष्ट। मेरे मामले में '...' को '{}' से बदल दिया गया था। बम, पूरी तरह से एक निर्भरता हटा दिया। – 2mia

+0

इसके साथ समस्या यह है कि आप अभी भी परीक्षण के अंदर अपनी सेवा का मज़ाक उड़ाते हैं। कहें कि आपको इसे कई स्थानों और कुछ बदलावों में नकल करने की आवश्यकता है। फिर आपको एक ही स्थान पर बदलने की बजाए प्रत्येक फाइल को बदलना होगा। रखरखाव के लिए वैलेंटाइन्स का जवाब स्वीकार किया जाना चाहिए (जो यह है)। – perry

24

मैं कॉफीस्क्रिप्ट में ऐसा कर रहा था और एक अतिरिक्त गोचा पाया। (इसके अलावा, मैं कोड इस पृष्ठ पर भ्रमित करने वाले संक्षिप्त हो पाया।) यहाँ एक पूरा काम कर उदाहरण है:

describe 'serviceA', -> 
    mockServiceB = {} 

    beforeEach module 'myApp' # (or just 'myApp.services') 

    beforeEach -> 
     angular.mock.module ($provide) -> 
     $provide.value 'serviceB', mockServiceB 
     null 

    serviceA = null 
    beforeEach inject ($injector) -> 
     serviceA = $injector.get 'serviceA' 

    it 'should work', -> 
     expect(true).toBe(true) 
     #serviceA.doStuff() 

स्पष्ट $provide.value के बाद अशक्त लौटने के बिना, मैं Error: Argument 'fn' is not a function, got Object हो रही है। मुझे इस Google Groups thread में जवाब मिला।

+1

'शून्य 'के बजाय खाली' वापसी' का उपयोग करने का प्रयास करें। इस तरह आपके जेनरेट किए गए जावास्क्रिप्ट में फ़ंक्शन के अंत में अतिरिक्त 'रिटर्न नल' लाइन नहीं होगी। इसके बजाय, आपका 'पहले से पहले' फ़ंक्शन कुछ भी वापस नहीं करेगा। – demisx

+0

इम पल में एक समान कोड का उपयोग करने की कोशिश कर रहा है, लेकिन मैं एक 'सिंटैक्स त्रुटि मिलती है: Unexpecte स्ट्रिंग 'serviceA'' अगर मैं अपने कोड का उपयोग करेंगे। इसे हल करने के बारे में कोई विचार? - इसके अलावा Coffeescript –

+0

@MathieuBrouwers का उपयोग कर, तो आप शायद एक नया सवाल खोलना चाहिए। मुझे यकीन है कि क्या आप वास्तव में संदर्भ दे रहे नहीं कर रहा हूँ, और मैं अपने कोड जवाब देने के लिए देखने के लिए होगा। – jab

1

यह मेरे लिए काम करता है। कुंजी एक वास्तविक मॉड्यूल को मजाक करने के लिए परिभाषित कर रहा है। कोणीय। Mock.module कॉलिंग वास्तविक मॉड्यूल mockable बनाता है और चीजों को जोड़ने की अनुमति देता है।

beforeEach(-> 
     @weather_service_url = '/weather_service_url' 
     @weather_provider_url = '/weather_provider_url' 
     @weather_provider_image = "test.jpeg" 
     @http_ret = 'http_works' 
     module = angular.module('mockModule',[]) 
     module.value('weather_service_url', @weather_service_url) 
     module.value('weather_provider_url', @weather_provider_url) 
     module.value('weather_provider_image', @weather_provider_image) 
     module.service('weather_bug_service', services.WeatherBugService) 

     angular.mock.module('mockModule') 

     inject(($httpBackend,weather_bug_service) => 
      @$httpBackend = $httpBackend 
      @$httpBackend.when('GET', @weather_service_url).respond(@http_ret) 
      @subject = weather_bug_service 
     ) 
    ) 
6

मुझे लगता है कि सबसे आसान तरीका केवल सेवा बी इंजेक्ट करना है और इसे नकली करना है। जैसे सेवा कार सेवा इंजन पर निर्भर करती है। अब हम जब कार का परीक्षण नकली इंजन की जरूरत है:

describe('Testing a car', function() { 
     var testEngine; 

    beforeEach(module('plunker')); 
    beforeEach(inject(function(engine){ 
    testEngine = engine; 
    })); 

    it('should drive slow with a slow engine', inject(function(car) { 
    spyOn(testEngine, 'speed').andReturn('slow'); 
    expect(car.drive()).toEqual('Driving: slow'); 
    })); 
}); 

संदर्भ: https://github.com/angular/angular.js/issues/1635