2009-05-04 18 views
6

मैं निर्भरता इंजेक्शन सीखने की कोशिश कर रहा हूं और एक समस्या में आया है, जब इकाई परीक्षण का परीक्षण करती है।निर्भरता इंजेक्शन समाधान और इकाई परीक्षण

मैं एक सांत्वना आवेदन लिख रहा हूँ और कंटेनर बनाया है और मुख्य() में आरंभ नहीं हो जाता, यह उपलब्ध है के रूप में Program.Container में एक get-property, इसलिए अपने आवेदन में कहीं भी मैं Program.Container.Resolve<..>() कॉल कर सकते हैं। मैं का उपयोग

ServiceValidator serviceValidator = Program.Container.Resolve<ServiceValidator>(); 
serviceValidator.VerifyVersion(); 

यह Program.Container.Resolve करने के लिए कॉल है कि मुझे इकाई परीक्षण में समस्याओं का कारण बनता है के रूप में यह नहीं है

public class ServiceValidator 
{ 
    private readonly IConfiguration _configuration; 
    private readonly IService _service; 

    public ServiceValidator(IConfiguration configuration, IService service) 
    { 
     _configuration = configuration; 
     _service = service; 
    } 

अन्य वर्ग में:

मैं इस तरह एक ServiceValidator वर्ग है सेटअप किया गया है।

क्या यह एक बुरा अभ्यास है, कंटेनर पर हल करने के लिए? मैं Main() में ServiceValidator इंस्टेंस बना सकता हूं और ऑब्जेक्ट को पास कर सकता हूं, लेकिन यह बेवकूफ लगता है क्योंकि इससे ऑब्जेक्ट्स के लिए बहुत से पैरामीटर होंगे जो अगली विधि के आसपास पास हो जाते हैं।

तो मुझे लगता है कि कॉल को कक्षा में हल करने के लिए स्वीकार्य है, लेकिन फिर कंटेनर को इकाई परीक्षण के लिए कॉन्फ़िगर किया जाना चाहिए। मुझे यह कैसे करना चाहिए, क्या मुझे कंटेनर को प्रोग्राम क्लास की तुलना में किसी अन्य स्थान पर ले जाना चाहिए? आप क्या सुझाव देंगे?

अगर यह मायने रखती है, मैं एकता उपयोग कर रहा हूँ और सी #

धन्यवाद :-)

उत्तर

8

क्या यह एक बुरा अभ्यास है, कंटेनर पर हल करने के लिए?मैं मुख्य() में ServiceValidator इंस्टेंस बना सकता हूं और ऑब्जेक्ट को पास कर सकता हूं, लेकिन यह बेवकूफ लगता है क्योंकि इससे ऑब्जेक्ट्स के लिए बहुत से पैरामीटर होंगे जो अगली विधि में पास हो जाते हैं।

जब आप निर्भरता इंजेक्शन का उपयोग सभी तरह से करते हैं, तो आपको ऑब्जेक्ट्स के कई पैरामीटर पारित करने की आवश्यकता नहीं होगी। प्रत्येक ऑब्जेक्ट के निर्माता को पैरामीटर के रूप में केवल उन निर्भरताओं के रूप में होना चाहिए जो इसे सीधे उपयोग करते हैं - यह इसकी प्रत्यक्ष निर्भरताओं की पारगमन निर्भरताओं के बारे में नहीं जान पाएगा।

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

अधिक जानकारी के लिए कुछ लिंक:

+0

> जब आप निर्भरता इंजेक्शन का उपयोग सभी तरह से करते हैं, > तो आपको ऑब्जेक्ट्स पर बहुत से पैरामीटर पास करने की आवश्यकता नहीं होगी। मैंने कभी भी सभी वर्गों के लिए DI करने पर विचार नहीं किया। मैं सिर्फ कक्षाओं के लिए DI करना चाहता था जो बाहरी सामान का उपयोग करता है, जैसे वेब सेवाएं, डेटाबेस, शायद कॉन्फ़िगरेशन। यदि मैं आपको सही समझता हूं, तो आप फ्रेमवर्क कक्षाओं के अलावा कुछ भी हल या नया नहीं कहेंगे? आपके उत्तर के लिए धन्यवाद :-) – Karsten

+0

एक और बात के बारे में सोचने के लिए आया था। क्या इसका मतलब यह है कि सभी वस्तुओं को सामने लाया जाता है, वास्तव में उनकी आवश्यकता होने से काफी समय पहले, शायद उन्हें भी जरूरी नहीं है? – Karsten

+0

DI का उपयोग करते समय, आप अपने अनुप्रयोग की रूट ऑब्जेक्ट को DI कंटेनर से प्राप्त करके एप्लिकेशन को बूटस्ट्रैप करते हैं, और इसके बाद आप कंटेनर को सीधे एक्सेस नहीं करते हैं। http://docs.google.com/Doc?id=dd2fhx4z_5df5hw8#xefn ऑब्जेक्ट्स बनाए जाएंगे जब कुछ ऑब्जेक्ट जो उन्हें निर्भरता के रूप में बनाए जाते हैं। आम तौर पर, एक ही जीवन चक्र के साथ सभी वस्तुओं को एक ही समय में तत्काल किया जाता है। अगर कुछ वस्तुओं के पास एक अलग जीवन चक्र गुंजाइश है, तो आप उन्हें सही समय पर तुरंत चालू करने के लिए एक कारखाने इंजेक्ट कर सकते हैं। –

1

मैं आमतौर पर कॉल मुख्य जैसी जगहों में कंटेनर से निर्भरता को हल करने, हालांकि मैं अभी भी उन्हें एक करने के लिए रखने की कोशिश की अनुमति देते हैं न्यूनतम। मैं जो करता हूं वह एक टेस्ट क्लास की प्रारंभिक विधि में कंटेनर को कॉन्फ़िगर करता है। मैंने इसे किसी टेस्ट क्लास के लिए नकली कार्यान्वयन के साथ शुरू किया है जिसे कंटेनर को कॉल करने की आवश्यकता है।

टेस्ट क्लास जो कंटेनर की शुरुआत करने के लिए कुछ भी कॉल नहीं करते हैं, वे इसे अनदेखा कर सकते हैं और नकली का उपयोग नहीं कर सकते हैं। मैं आमतौर पर उन मामलों में मोक्स का उपयोग करता हूं।

मैं Microsoft Service Locator का भी उपयोग करता हूं ताकि मैं जो निर्भरता ले रहा हूं वह एक विशिष्ट कंटेनर के बजाय .NET Framework से कुछ पर है। इससे मुझे सड़क के उपयोग को कम करने की अनुमति मिलती है, जिसे मैं घर के ब्रीड कंटेनर भी चाहता हूं।

+0

मैं अभी भी कार्यक्रम वर्ग ... –

+0

पर निर्भरता बनाने के बिना यह कैसे हल करने के लिए एक अच्छा पैटर्न देखना चाहेंगे> मुझे लगता है कि जैसे कॉल रखना .. आप 'संकल्प' का मतलब क्या कंटेनर के लिए कॉल ? – Karsten

+0

हां, मेरा मतलब है कंटेनर को 'हल करें' कॉल। –

0

आप अपने कंटेनर के लिए प्रारंभिक के रूप में एक स्थिर वर्ग का उपयोग कर सकते हैं। BootStrapper.cs की तरह कुछ ठीक होगा। फिर आप अपने कोड और परीक्षण दोनों में कक्षा विधियों का संदर्भ दे सकते हैं।

0

वैसे जो आप तकनीकी रूप से कर रहे हैं वह आपकी कक्षा में एक सेवा स्थान है।

मैं एक समय पहले यह लेख पढ़ याद:

http://martinfowler.com/articles/injection.html

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

0

समस्या में निहित है तथ्य यह है कि आप मुख्य विधि का परीक्षण करने की कोशिश कर रहे हैं। यह विधि इकाई परीक्षण के लिए लगभग असंभव है।

मैं तर्क था कि यह अपने मुख्य विधि का परीक्षण क्योंकि इकाई न जाया जाए:

  • आधुनिक इकाई परीक्षण का जोर डिजाइन
  • आप इकाई परीक्षण में विन्यास पर निर्भरता को कम करना चाहिए के बारे में है। कॉन्फ़िगरेशन का परीक्षण धूम्रपान या एकीकरण परीक्षण के साथ किया जा सकता है।
+0

नहीं, मैं मुख्य विधि का परीक्षण करने की कोशिश नहीं करता हूं। – Karsten

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