2012-04-02 20 views
5

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

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

मैं अपने यूनिट परीक्षण फिक्स्चर में इसका उपयोग कैसे करूं?

public class TaxCalculator 
{ 
    private ExceptionManager _exceptionManager; 
    private LogWriter _logWriter; 

    public TaxCalculator(ExceptionManager em, LogWriter lw) 
    { 
    this._exceptionManager = em; 
    this._logWriter = lw; 
    } 
} 

उत्तर

9

प्रश्न का उत्तर देने के लिए "मैं एंटरप्राइज़ लाइब्रेरी कोड" का परीक्षण कैसे करूं: आप नहीं करते। अन्य लोगों की सामग्री का परीक्षण अन्य लोगों का काम है। एंटरप्राइज़ लाइब्रेरी या किसी अन्य तृतीय-पक्ष लाइब्रेरी में कोई भी इंटरफेस या अबास्ट्रक्शन आपके स्वयं के अमूर्त उद्देश्यों के लिए मौजूद है, न कि आपके लिए।

आपको अपने स्वयं के इंटरफेस को परिभाषित करने की आवश्यकता है जो आपके आवेदन (लॉगिंग, कैशिंग, एन्क्रिप्शन इत्यादि) की आवश्यकताओं का वर्णन करती है और फिर एडेप्टर लिखती हैं जो एंटरप्राइज़ लाइब्रेरी (या अन्य तृतीय-पक्ष पुस्तकालयों) का उपयोग करके आपके इंटरफेस को लागू करती हैं। । इस अभ्यास को Dependency Inversion Principle के रूप में जाना जाता है।

इस तरह से डिज़ाइन किए गए अपने स्वयं के कोड का परीक्षण करने के लिए, इकाई/घटक स्तर परीक्षणों के लिए आप केवल उन इंटरफेस के लिए टेस्ट डबल्स का उपयोग करेंगे जिन्हें आपने स्वयं परिभाषित किया है (उदा। IMyOwnLogger)। तृतीय पक्ष पुस्तकालयों को अनुकूलित करने के लिए आपके द्वारा लिखे गए एडाप्टर का परीक्षण करने के लिए, आप एकीकरण परीक्षण लिखेंगे। यह जांचने के लिए कि यह सब एक साथ काम करता है, आप स्वीकृति परीक्षण लिखेंगे जो यूआई या उपनिवेश के माध्यम से ऐप ड्राइव करेगा।

इस दृश्य के बारे में अधिक जानकारी के लिए, मेरा आलेख देखें: "TDD Best Practices: Don't Mock Others"।

+0

मैंने इस तथ्य को प्रतिबिंबित करने के लिए शीर्षक बदल दिया कि मैं एंटरप्राइज़ लाइब्रेरी का परीक्षण नहीं करना चाहता हूं लेकिन मेरा स्वयं का कोड एंटरप्राइज़ लाइब्रेरी पर निर्भर करता है। –

+0

मैंने स्पष्ट रूप से बोलने के लिए उत्तर अपडेट किया है कि बाहरी निर्भरताओं के प्रकाश में आप अपने कोड का परीक्षण कैसे करेंगे। –

+0

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

4

यह बजाय अमूर्त कार्यान्वयन के खिलाफ कार्यक्रम बेहतर है: उनके उदाहरण इंटरफेस के बजाय वर्ग के रूप में मानकों के साथ एक निर्माता है। लेकिन अमूर्त हमेशा इंटरफेस नहीं है। यह अमूर्त वर्ग हो सकता है।

public abstract class LogWriter 
{ 
    public abstract void Write(string message); 
} 

इसलिए, अमूर्त वर्ग के नकली बनाने के लिए कोई समस्या नहीं है:

Mock<LogWriter> logWriter = new Mock<LogWriter>(); 
TaxCalculator calc = new TaxCalculator(logWriter.Object); 

आप इकाई परीक्षण नहीं कर रही है, मैं गैर सार पैरामीटर भेजने के लिए किसी भी समस्या नहीं दिख रहा है, क्योंकि YAGNI सिद्धांत के। अगर मुझे अपवाद प्रबंधक के दूसरे कार्यान्वयन की आवश्यकता नहीं है, तो मुझे इसके ऊपर अमूर्त क्यों बनाना चाहिए? लेकिन अगर मैं टीडीडी करता हूं, तो मुझे निश्चित रूप से कक्षा के कम से कम दो कार्यान्वयन की आवश्यकता होगी। एक असली और एक नकली/स्टब।

बीटीडब्ल्यू service locator anti-pattern से सावधान रहें।

अद्यतन: यह नहीं मिला कि आप माइक्रोसॉफ्ट के मौजूदा वर्गों का जिक्र कर रहे हैं। व्यवहार। एंटरप्राइज लाइब्रेरी (जो मुझे पसंद नहीं है)। मुझे लगता है कि माइक्रोसॉफ्ट की एक और डिजाइन विफलता है। अभ्यास टीम। 'मुहरबंद' अपवाद प्रबंधक वर्ग जो किसी भी इंटरफेस/बेस क्लास को लागू नहीं करता है, टेस्टेबिलिटी को मारता है।

+0

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

+0

तो, आपको लगता है उदा। Log4net में ILog मुझे उपयोग करने के लिए एक अमूर्त प्रदान नहीं है? –

+0

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

3

जब तक आपकी कक्षा sealed नहीं होती है, तब तक एक सक्षम मॉकिंग फ्रेमवर्क एक उप-वर्ग बना सकता है जो एक मॉक इंटरफ़ेस कार्यान्वयन की तरह कार्य करता है। जब आप कंक्रीट कक्षाओं पर निर्भर होते हैं तो बनाने के लिए और अधिक विचार हैं - sealed विधियां अभी भी निर्दिष्ट कक्षा आदि पर निष्पादित होंगी - लेकिन सामान्य में यह इंटरफ़ेस के आधार पर अलग नहीं है।