2010-10-11 9 views
7

मान लें कि हम एक कक्षा सी का परीक्षण कर रहे हैं जिसमें 2 विधियों एम 1 और एम 2 हैं जहां एम 1 निष्पादित होने पर एम 2 को कॉल करता है।एक विधि का नकल कैसे करें जो लक्ष्य वर्ग से भी संबंधित है?

परीक्षण एम 2 ठीक है, लेकिन हम एम 1 का परीक्षण कैसे कर सकते हैं? कठिनाई यह है कि अगर मैं चीजों को गलत समझ नहीं पा रहा हूं तो हमें एम 2 का नकल करने की जरूरत है।

यदि हां, तो हम उसी वर्ग में परिभाषित विधि का परीक्षण करते समय एक और विधि कैसे बना सकते हैं?

[संपादित करें]
कक्षा सी में कोई आधार वर्ग नहीं है।

+0

क्या आप स्पष्ट कर सकते हैं कि इसमें शामिल मूल कक्षाएं हैं या नहीं? –

+0

@ रूबेन: मेरे मामले में कोई आधार वर्ग (कक्षा सी)। –

उत्तर

7

आप संपत्ति को true पर नकली पर सेट करके कर सकते हैं।

उदाहरण के लिए, अगर मैं इस वर्ग है:

public class Foo 
{ 
    public virtual string MethodA() 
    { 
     return "A"; 
    } 
    public virtual string MethodB() 
    { 
     return MethodA() + "B"; 
    } 
} 

मैं कर सकते हैं सेटअप MethodA और फोन MethodB:

[Fact] 
public void RunTest() 
{ 
    Mock<Foo> mockFoo = new Mock<Foo>(); 
    mockFoo.Setup(x => x.MethodA()).Returns("Mock"); 
    mockFoo.CallBase = true; 

    string result = mockFoo.Object.MethodB(); 

    Assert.Equal("MockB", result); 
} 
+0

@ रूबेन बार्टेलिंक, मुझे यकीन नहीं है कि यह मेरा जवाब क्यों बदल देगा। मेरे उत्तर में परीक्षण के तहत कक्षा में बेस क्लास भी नहीं है। –

+0

+1 आप बिल्कुल सही हैं (मैंने समस्या के बारे में आपका जवाब या विचार नहीं पढ़ा था), मेरी पहली टिप्पणी हटाना; यह टिप्पणी गायब हो जाएगी अगर +1 –

6

आप की एक वास्तविक उदाहरण के लिए के माध्यम से M1 पास करने के लिए कॉल देना चाहिए M2 विधि।

सामान्य रूप से, आपको ब्लैक बॉक्स अपने वर्गों के व्यवहार का परीक्षण करना चाहिए। आपके परीक्षणों पर ध्यान नहीं दिया जाना चाहिए कि M1M2 पर कॉल करने के लिए होता है - यह एक कार्यान्वयन विवरण है।

यह मजाक बाहरी निर्भरता (आपको क्या करना चाहिए जो) के रूप में ही नहीं है ...


उदाहरण के लिए, मैं इस तरह एक वर्ग है:

class AccountMerger 
{ 
    public AccountMerger(IAccountDao dao) 
    { 
     this.dao = dao; 
    }  

    public void Merge(Account first, Account second, MergeStrategy strategy) 
    { 
     // merge logic goes here... 
     // [...] 
     dao.Save(first); 
     dao.Save(second); 
    } 

    public void Merge(Account first, Account second) 
    { 
     Merge(first, second, MergeStrategy.Default); 
    } 

    private readonly IAccountDao dao; 
} 

मैं अपने परीक्षणों को यह दिखाने के लिए चाहता हूं कि:

  1. कॉलिंग Merge(first, second, strategy) परिणामस्वरूप दो खाते सहेजे जा रहे हैं जिन्हें आपूर्ति किए गए नियम का उपयोग करके विलय कर दिया गया है।

  2. कॉलिंग Merge(first, second) परिणामस्वरूप दो खाते सहेजे गए हैं जिन्हें डिफ़ॉल्ट नियम का उपयोग करके विलय कर दिया गया है।

ध्यान दें कि इन आवश्यकताओं के दोनों आदानों और प्रभाव के संदर्भ में phrased रहे हैं - विशेष रूप से, मुझे परवाह नहीं है कैसे वर्ग इन परिणामों को प्राप्त होता है, जब तक यह करता है।

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

// ... 
    // refactored AccountMerger methods 
    // these still work, and still fulfil the two requirements above 

    public void Merge(Account first, Account second, MergeStrategy strategy) 
    { 
     MergeAndSave(first, second, strategy ?? MergeStrategy.Default); 
    } 

    public void Merge(Account first, Account second) 
    { 
     // note this no longer calls the other Merge() method 
     MergeAndSave(first, second, MergeStrategy.Default); 
    } 

    private void MergeAndSave(Account first, Account second, MergeStrategy strategy) 
    { 
     // merge logic goes here... 
     // [...] 
     dao.Save(first); 
     dao.Save(second); 
    } 

    // ... 

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

दूसरी ओर, मैं किसी मर्ज (हालांकि AccountMerger डीएओ के कार्यान्वयन के बारे में परवाह नहीं करना चाहिए, यह एक Save() विधि है ही नहीं।) यह डीएओ है निम्न खातों को बचाने के लिए IAccountDao का उपयोग कर के बारे में क्या AccountMerger मॉकिंग के लिए एक प्रमुख उम्मीदवार - बाहरीAccountMerger वर्ग की निर्भरता, प्रभाव महसूस करना मैं कुछ इनपुट के लिए जांचना चाहता हूं।

+0

मुझे यह नहीं मिला। अगर मैं कक्षा को काले बॉक्स के रूप में मानता हूं, तो मुझे कैसे पता चलेगा कि मुझे क्या नकल करना चाहिए? –

+0

@Nam: उत्तर में जोड़े गए उदाहरण को देखें ... –

4

आपको लक्ष्य वर्ग में विधियों का नकल नहीं करना चाहिए, आपको केवल बाहरी निर्भरताओं का नकल करना चाहिए।

यदि एम 1 का परीक्षण करते समय एम 2 का नकल करना समझ में आता है तो अक्सर इसका मतलब है कि आपकी कक्षा बहुत सी चीजें कर रही है। कक्षा को विभाजित करने और एम 2 को एक वर्ग में रखने पर विचार करें और एम 1 को उच्च स्तर की कक्षा में ले जाएं, जो एम 2 युक्त कक्षा का उपयोग करेगा। फिर एम 2 का मज़ाक करना आसान है, और आपका कोड वास्तव में बेहतर हो जाएगा।

+0

यह मुझे आंतरिक निर्भरताओं का नकल करने की इच्छा की तरह लगता है, यहां तक ​​कि स्प्रिंग्स ने "कई चीज़ों का परीक्षण" करने के बजाय सिद्धांत को बहुत अधिक काम करने के बजाय । इसके माध्यम से ओओपी को पूरी तरह से छोड़कर और प्रक्रियात्मक प्रोग्रामिंग पर वापस जाने का मतलब होगा। –

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