2010-10-19 16 views
8

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

यह आप में से अधिकांश के लिए वास्तव में मूर्ख सवाल हो सकता है लेकिन कुछ सुझाव बहुत अच्छे होंगे और मैं सिर्फ यह जानना चाहता हूं कि यहां विशेषज्ञ कैसे स्थिर सामग्री के बारे में सोचते हैं। अग्रिम धन्यवाद।

संपादित करें: उत्तर की तलाश में मुझे 2 अन्य स्थैतिक उपयोग के संबंध में अच्छे धागे (हालांकि टीडीडी चिंता नहीं) जो मैं अनुमान रुचि रखने वालों के लिए अच्छा पढ़ा जाता है (स्वयं समावेशी)।

उत्तर

11

मैं तुम्हें थोड़ा गलत समझा हो सकता है लगता है।

स्टेटिक विधियां टेस्टेबल हैं। एक उदाहरण के रूप इस विधि लें:

public static int Add(int x, int y) 
{ 
    return x + y; 
} 

आप परीक्षण है कि वापसी मान क्या आप तर्क में पारित के आधार पर उम्मीद है के द्वारा इस परीक्षण कर सकते हैं

कहाँ स्थिर तरीकों परेशानी हो जाते हैं जब परीक्षण जब आप की जरूरत है। एक नकली पेश करने के लिए।

मान लें कि मेरे पास कुछ कोड है जो File.Delete() स्थैतिक विधि को कॉल करता है। फ़ाइल सिस्टम पर भरोसा किए बिना मेरे कोड का परीक्षण करने के लिए, मैं इस कॉल को एक टेस्ट संस्करण के साथ प्रतिस्थापित/मॉक करना चाहता हूं जो सिर्फ सत्यापित करता है कि इसे कोड के परीक्षण से बुलाया गया है। यह करना आसान है अगर मेरे पास उस ऑब्जेक्ट का उदाहरण था जिस पर Delete() कहा जा रहा था। अधिकांश (सभी?) मॉकिंग फ्रेमवर्क स्थिर तरीकों का नकल नहीं कर सकते हैं, इसलिए मेरे कोड में एक स्थिर विधि का उपयोग करके मुझे इसे अलग-अलग परीक्षण करने के लिए मजबूर किया जाता है (आमतौर पर वास्तविक स्थैतिक विधि को कॉल करके)।

कुछ इस तरह का परीक्षण करने के लिए, मैं एक इंटरफेस को पेश होगा:

interface IFileDeleter 
{ 
    void Delete(string file); 
} 

मेरे कोड तो एक वस्तु है कि इस इंटरफेस (लागू करता है या तो विधि कॉल में या निर्माता में पैरामीटर के रूप का एक उदाहरण ले जाएगा), और फिर हटाएं करने के लिए अपने Delete() विधि कॉल:

void MyMethod(string file) 
{ 
    // do whatever... 
    deleter.Delete(file); 
} 

इस परीक्षण के लिए, मैं IFileDeleter इंटरफ़ेस का एक नकली कर सकते हैं और आसानी से सत्यापित करें कि उसका Delete() विधि बुलाया गया था। यह परीक्षण के हिस्से के रूप में एक असली फाइल सिस्टम की आवश्यकता को हटा देता है।

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

+0

+1! Typemock स्थैतिक तरीकों का नकल कर सकते हैं, लेकिन उनसे बचने के लिए बेहतर है (जब उन्हें मजाक करने की आवश्यकता होगी)। – TrueWill

+0

+1 एक व्यापक उत्तर के लिए धन्यवाद ढेर। मैं ज्ञान साझा करने के लिए उत्तर चुनने से पहले कुछ और उत्तरों (यदि कोई हो) की प्रतीक्षा करूँगा – MSI

+0

एचएम जो मैंने पूछा वह वास्तव में थोड़ा मूर्ख था, जिसे मैंने आपका जवाब पढ़ा था। हाँ, जब आप सवाल पूछते हैं तो मैं सही कहता हूं। जब वे असली परेशानी पैदा करते हैं तो यह मजाक कर रहा है; विधि का परीक्षण स्वयं विशेष रूप से नहीं करते जब यह केवल एक उपयोगिता विधि है। – MSI

7

सामान्य में, अगर विधि:

  • धीमी
  • है लंबे
  • जटिल तर्क
  • फाइल सिस्टम
  • एक डेटाबेस
  • से कनेक्ट करता होती है जिसका उपयोग है एक वेब कॉल सेवा

फिर इसे स्थिर बनाने से बचें। (इस और विकल्पों के पीछे कारणों के बारे में उत्कृष्ट चर्चा के लिए @adrianbanks का उत्तर देखें।)

असल में, केवल यह स्थिर बना देता है यदि यह एक छोटी स्मृति सुविधा सुविधा (जैसे कई एक्सटेंशन विधियों) है।

+0

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

8

स्थिरता से बचने का निश्चित रूप से जाने का तरीका है, लेकिन जब आप लीगेसी कोड के साथ काम नहीं कर रहे हैं, तो निम्न विकल्प उपलब्ध है। adrianbanks से इसे जारी रखते हुए ऊपर का जवाब, मान लीजिए कि आप कोड निम्नलिखित डालते हैं (क्षमा याचना, अपने जावा में मैं सी # पता नहीं है के रूप में):

public void someMethod() { 
    //do somethings 
    File.delete(); 
    //do some more things 
} 

आप की तरह अपनी ही विधि में File.delete() refactor कर सकते हैं इस:

public void someMethod() { 
    //do somethings 
    deleteFile(); 
    //do some more things 
} 

//protected allows you to override in a subclass 
protected void deleteFile() { 
    File.delete(); 
} 

और फिर अपने इकाई परीक्षण के लिए तैयारी में एक नकली वर्ग जो मूल एक और है कि कार्यक्षमता बाहर स्टब्स फैली बनाएँ:

//Keep all the original functionality, but stub out the file delete functionality to 
//prevent it from using the real thing and while you're at it, keep a record that the 
//method was called. 
public class MockClass extends TheRealClass { 
    boolean fileDeleteCalled = false; 

    @Override 
    protected void deleteFile() 
     //don't actually delete the file, 
     //just record that the method to do so was called 
     fileDeleteCalled = true; 
    } 

    public boolean fileDeleteCalled() { 
     return fileDeleteCalled; 
    } 
} 

और अंत में अपने इकाई परीक्षण में:

//This would normally be instantiated in the @Before method 
private MockClass unitUnderTest = new MockClass(); 

@Test 
public void testFileGetsDeleted(){ 
    assertFalse(unitUnderTest.fileDeleteCalled()); 
    unitUnderTest.someMethod(); 
    assertTrue(unitUnderTest.fileDeleteCalled()); 
} 

अब आप वास्तव में फ़ाइल को हटाने के बिना someMethod() की सभी कार्यक्षमता निष्पादित कर दिया है, और आप अभी भी देखने के लिए यदि इस विधि का कहा जाता था की क्षमता है।

+0

+1। धन्यवाद साथी – MSI

+0

कोई व्यक्ति उसे अधिक उदाहरण देता है कृपया अच्छे उदाहरण और स्पष्टीकरण के लिए – MSI

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