2009-11-02 19 views
9

करते समय नकली करने के लिए कौन सी ऑब्जेक्ट्स विधि बनाते समय, उस विधि के अंदर तत्काल प्रत्येक ऑब्जेक्ट को पैरामीटर के रूप में पारित किया जाना चाहिए ताकि उन वस्तुओं को हमारे यूनिट परीक्षणों में मजाक किया जा सके?टीडीडी

हमारे यहां काम पर बहुत सारी विधियां हैं जिनके पास कोई यूनिट परीक्षण नहीं है और परीक्षणों को पीछे से लिखने पर; हम पाते हैं कि इन विधियों के अंदर तुरंत बहुत सारी वस्तुएं हैं।

हमारे विकल्पों में से एक है हमारे मौजूदा तरीकों को विधियों की तरह अधिक इकाई में पुन: सक्रिय करना और प्रति तरीकों की जिम्मेदारियों को कम करना। यह काफी लंबी प्रक्रिया हो सकती है लेकिन भविष्य में निश्चित रूप से हमारे लिए एक बड़ा लाभ होगा।

आपको क्या लगता है? क्या किसी विधि के अंदर तत्काल सभी ऑब्जेक्ट्स पैरामीटर के रूप में पारित किए जाने चाहिए?

+0

"उस विधि के अंदर तत्काल प्रत्येक ऑब्जेक्ट को पारित किया जाना चाहिए" आप इसे फिर से लिखना चाहते हैं। यह भ्रमित करने वाला है। मुझे लगता है कि आप पूछ रहे हैं कि "* * के बजाय तत्काल * विधि में उन्हें पारित किया जाना चाहिए"। अगर इन्हें अल्टेरेटिव माना जाता है तो यह थोड़ा और समझ में आता है। समानता के लिए –

उत्तर

7

शायद सभी ऑब्जेक्ट्स नहीं, लेकिन जितनी अधिक ऑब्जेक्ट्स आप अपनी इकाई में इंजेक्ट करते हैं, उतना ही बेहतर चिंताएं अलग हो जाती हैं, इसलिए मैं निश्चित रूप से अनुशंसा करता हूं कि आप उस दिशा में आगे बढ़ें।

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

public class Foo 
{ 
    private readonly IBar bar; 

    public Foo(IBar bar) 
    { 
     this.bar = bar; 
    } 

    public Ploeh DoStuff(Fnaah f) 
    { 
     return this.bar.DoIt(f); 
    } 
} 

सूचना है कि मैं एक उदाहरण के लिए बार का एक उदाहरण से bar बदल दिया है:

public class Foo 
{ 
    public Ploeh DoStuff(Fnaah f) 
    { 
     var bar = new Bar(); 
     return bar.DoIt(f); 
    } 
} 

यह इस तरह देखने के लिए बदला जा सकता है:

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

6

पहला भाग एक लोड प्रश्न का थोड़ा सा है। यह पूछने की तरह है "जब मेरी कार में पैदल चलने वालों पर दौड़ते हैं, तो क्या मेरे पास पहिया पर दोनों हाथ होना चाहिए?"

एक ऐसी विधि जो अन्य कई वस्तुओं को तुरंत चालू कर रही है, लगभग निश्चित रूप से बहुत अधिक कर रही है। उन विधियों के साथ एक वर्ग शायद एक जिम्मेदारी सिद्धांत का पालन नहीं कर रहा है।

हालांकि, आपके कोड को टेस्ट करने योग्य बनाने के प्रमुख तरीकों में से एक आईओसी (नियंत्रण में उलटा) का उपयोग करना है, जहां कक्षा के बजाय कक्षा की निर्भरता (या एक विधि) पास की जाती है। इससे परीक्षण करना बहुत आसान हो जाता है, क्योंकि आप मोक्स में गुजर सकते हैं।

तो संक्षिप्त उत्तर "हां" है, अपनी निर्भरताओं में गुजरें और dependency injection घटक देखें। लंबा जवाब है "हां, लेकिन ऐसा मत करो"। डी ढांचे शायद आपको विधियों के बजाय वस्तुओं पर निर्भरताओं में पारित करने के लिए मजबूर करेंगे, और आप पाएंगे कि आप यह सुनिश्चित करना चाहते हैं कि आप उन निर्भरताओं को सीमित करें - जो एक अच्छी बात है।

और निश्चित रूप से, निर्भरताओं को कम करने के लिए प्रतिक्रिया करना अच्छा है। एक चीज करने के लिए अपने तरीकों को छोटा करना लगभग कभी बुरा नहीं होता है। मैं दृढ़ता से सहमत हूं कि यह एक दीर्घकालिक लाभ है, जब तक कि आप अल्पकालिक लागतों का भुगतान कर सकें।

+1

+1। यह सोमवार है और मुझे एक अच्छी हंसी की जरूरत है। – wheaties

1

किसी बिंदु पर आप किसी ऑब्जेक्ट से किसी ऑब्जेक्ट से बनाने से दूर नहीं जा रहे हैं, लेकिन आपको अच्छे डिज़ाइन सिद्धांतों के लिए सॉफ्टवेयर लिखना चाहिए। जैसे एसआरपी, डी आदि ..

जहां आपके पास कई निर्भरताएं हैं, आपको एक आईओसी कंटेनर मिल सकता है ताकि आप उन्हें प्रबंधित कर सकें।

विरासत कोड से निपटने पर, आपको माइकल फेदर के Working Effectively with Legacy code पढ़ने के लिए उपयोगी लगता है। इस पुस्तक में आपकी तकनीक को परीक्षण के तहत कैसे प्राप्त किया जाए इस पर कई तकनीकें हैं।

0

मुझे यकीन है कि आप उपयोग कर रहे हैं क्या भाषा/उपकरण नहीं कर रहा हूँ, लेकिन जिस तरह से यह किया जा सकता है यह रेल बस निर्माता उपहास करने के लिए है, इसलिए की तरह है:

@user = mock_model(User) 
User.stub(:create).and_return(@user) 

तो अब से में

अपने यदि आप User.create (उपयोगकर्ता "क्लास") कहते हैं तो परीक्षण करें, यह हमेशा आपके पूर्वनिर्धारित @user चर को वापस कर देगा, जिससे आप अपने यूनिट परीक्षणों में किस डेटा का उपयोग कर रहे हैं इसका कुल नियंत्रण कर सकते हैं।

अब जब आप जानते हैं कि आपके परीक्षणों में वास्तव में कौन सा डेटा है, तो आप यह सुनिश्चित करने के लिए अपनी ऑब्जेक्ट्स के इंस्टेंस विधियों को स्टब करना शुरू कर सकते हैं कि वे आपके डेटा का परीक्षण करने के लिए उपयोग कर सकने वाले उचित डेटा को वापस कर रहे हैं।

0

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

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

2

बस एक अवलोकन: आप विधियों के बारे में बात करना पसंद करते हैं, जबकि आप विधियों के बारे में बात कर रहे हैं।

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

पर विचार करें:

  • अगर एक वर्ग एक और का उपयोग करता है, लेकिन आप शिथिल उन्हें जोड़ी, तो आप एक इंटरफेस का उपयोग करना चाहिए करना चाहता हूँ। अब, अगर केवल इंटरफ़ेस ज्ञात है, ठोस प्रकार नहीं, तो प्रथम श्रेणी को उदाहरण कैसे बनाना चाहिए?
  • decoupling कक्षाएं बहुत महत्वपूर्ण हैं, लेकिन हर मामले में नहीं किया जा सकता है और नहीं किया जाना चाहिए। यदि संदेह में है, तो decoupled किया जाना चाहिए।
  • इंजेक्शन का उपयोग करते समय, आपको तय करना होगा जो उदाहरण बना रहा है और इंजेक्शन दे रहा है। आपको शायद स्प्रिंग.Net जैसे निर्भरता इंजेक्शन ढांचे को आसानी से मिल जाएगा।

एक और चाल है: इंजेक्शन वैकल्पिक बनाएं। इसका मतलब है, जब आप निर्माता में एक उदाहरण पास करते हैं, तो इसका उपयोग किया जाएगा। जब नहीं, कक्षा द्वारा स्वयं एक नया उदाहरण बनाया जाता है। यह विरासत कोड से निपटने के दौरान आसान है और जब आपके पास निर्भरता इंजेक्शन ढांचा नहीं है।

2

[अस्वीकरण: मैं Typemock पर काम]
आप तीन विकल्प हैं - दो जिनमें से कुछ पुनर्रचना की आवश्यकता है:

  1. पास सभी तर्क - आप पहले से ही इस तरह से आप mocks/स्टब्स पारित कर सकते हैं पता है की तरह "असली" वस्तुओं के बजाय।
  2. आईओसी कंटेनर का उपयोग करें - अपने कोड से वस्तुओं को पकड़ने के लिए कंटेनर का उपयोग करने के लिए अपने कोड को दोबारा दोहराएं और आप उन्हें मोक्स/स्टब्स से बदल सकते हैं।
  3. Typemock Isolator (.NET) का उपयोग करें जो नकली भविष्य की वस्तुओं - ऑब्जेक्ट्स जो आपके कोड के अंदर टेस्ट कोड से तत्काल हो। इस विकल्प को रिफैक्टरिंग की आवश्यकता नहीं है और यदि आपके पास एक बड़ा कोड आधार है तो यह इसके कोड के लायक होना चाहिए। testability के लिए

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

यदि आप अपने सभी मौजूदा कोड को बदलना नहीं चाहते हैं और/या इसे "अधिक टेस्टेबल" बनाने के लिए अपने कोड को किसी निश्चित तरीके से डिज़ाइन नहीं करना चाहते हैं (कुछ विचित्र दिखने वाले कोड का कारण बन सकते हैं - Isolator (या समान उपकरण यदि आप जावा का उपयोग कर रहे हैं)

2

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

उपयोग नकली जब आप अन्य से एक वर्ग को अलग करना चाहते हैं। नकली का उपयोग करें ताकि परीक्षण

से दूर रखने के
  • फ़ाइल सिस्टम
  • डेटाबेस
  • नेटवर्क
  • अप्रत्याशित व्यवहार के साथ
  • वस्तु (घड़ी, यादृच्छिक संख्या जनरेटर ...)

उनके निर्माण से वस्तु की अलग-अलग उपयोग

0

मैं करने की कोशिश करेगा क्लास विधि ऑब्जेक्ट बनाने के बजाए कक्षा पर निर्भरता इंजेक्शन का उपयोग करें (जैसा कि चयनित उत्तर अनुशंसा करता है)। जब यह समझ में नहीं आता है, तो फैक्ट्री क्लास बनाने पर विचार करें जो वस्तुओं को उत्पन्न करता है। फिर आप निर्भरता इंजेक्शन के माध्यम से उस कारखाने में गुजर सकते हैं।

0

मैं किसी ऑब्जेक्ट के चारों ओर सबकुछ के बारे में नकल करना पसंद करता हूं, और ऑब्जेक्ट के व्यवहार को परिभाषित करता हूं जिसे कॉल के संदर्भ में और संबंधित वस्तुओं से प्रतिक्रियाओं के संदर्भ में परीक्षण किया जा रहा है।

ऐसा करने के लिए प्रभावी रूप से यह आवश्यक है कि आपके इंटरफेस सामान्य रूप से कार्यान्वयन स्तर की बजाय अर्थात् स्तर पर हों।

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