2011-09-02 14 views
5

यह मेरा पहला सवाल है इसलिए कृपया दयालु रहें! :)कोई वापसी मूल्य वाले विधि का परीक्षण करने के लिए Moq का उपयोग कैसे करें?

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

प्रबंधक वर्ग मेरा कोड है, लेकिन एकल आइटम वर्ग ऐसा नहीं है इसलिए मैं इसे संशोधित नहीं कर सकता।

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

मैं अपने UpdateAllItems विधि के लिए परीक्षण कैसे लिखूं? (तकनीकी रूप से मुझे पहले परीक्षणों को लिखना चाहिए)।

यहाँ एक कुछ नमूना कोड है कि क्या मैं के साथ काम कर रहा हूँ की एक सामान्य विचार देता है ... सभी मदद के लिए

public class SingleItem_CodeCantBeModified 
{ 
    public int CurrentValue { get; private set; } 

    public SingleItem_CodeCantBeModified(int startValue) 
    { 
     CurrentValue = startValue; 
    } 

    public void Increment() 
    { 
     CurrentValue++; 
    } 
} 

public class SingleItemManager 
{ 
    List<SingleItem_CodeCantBeModified> items = new List<SingleItem_CodeCantBeModified>(); 

    public SingleItemManager() 
    { 
     items.Add(new SingleItem_CodeCantBeModified(100)); 
     items.Add(new SingleItem_CodeCantBeModified(200)); 
    } 

    public void UpdateAllItems() 
    { 
     items.ForEach(item => item.Increment()); 
    } 
} 

धन्यवाद!

+0

यह कक्षा कैसे उपयोगी है? यह काउंटर की एक निजी सूची बनाता है और हर बार एक विधि कहलाता है जब प्रत्येक आइटम अद्यतन करता है। ऑब्जेक्ट के व्यवहार में कुछ बदलाव होना चाहिए .. उदा। अगर UpdateAllItems काम नहीं करता है - परिवर्तन क्या देखा जाएगा? – Gishu

उत्तर

5

सरल उत्तर यह है कि आप नहीं कर सकते। विधि UpdateAllItems कॉल (Increment()) गैर-वर्चुअल है, इसलिए आप इसे नकल करने में सक्षम नहीं होंगे।

आपके विकल्प, के रूप में मैं इसे देख, कर रहे हैं:

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

कि अंतिम विकल्प प्रदान करती है अधिकतर विकल्प, लेकिन कुछ जटिलता की कीमत पर। वह विकल्प चुनें जो आप पूरा करने की कोशिश कर रहे हैं उसके लिए सबसे उपयुक्त है।

1

आपका प्रबंधक आइटम पर बहुत निर्भर है (List<Item> में)। क्या आप सूची जनसंख्या को अलग-अलग वर्ग में निकाल सकते हैं ताकि इसे नकल करने में सक्षम हो सके? उदाहरण के लिए:

public SingleItemManager() 
{ 
    items.Add(ItemRepository.Get(100)); 
    items.Add(ItemRepository.Get(200)); 
} 

परीक्षण (कुछ कोड छोड़े गए):

int i = 0; 

var itemMock = new Mock<Item>(); 
itemMock.Setup(i => i.Increment()).Callback(() => i++); 

var repositoryMock = new Moc<ItemRepository>(); 
repositoryMock.Setup(r => r.Get(It.IsAny<int>()).Returns(itemMock.Object); 

var manager = new SingleItemManager(); 
manager.UpdateAllItems(); 

Assert.AreEqual(i, 1); 
-1

के बजाय हार्ड-कोड आपके अतिरिक्त ठोस आइटम, (SingleItem_CodeCantBeModified एक इंटरफ़ेस को लागू नहीं है या एक आवरण जो इंटरफेस को लागू करता है में एम्बेड) फिर एक (नया) कारखाना पास करें जो इन वस्तुओं को बनाएगा।

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

हालांकि यह सिस्टम के आंतरिक परीक्षणों के बारे में अधिक होगा, उपज नहीं। प्रबंधक क्या इंटरफेस लागू कर रहा है? यदि यह स्वयं को बाहरी रूप से साबित नहीं कर रहा है, तो आप किस नतीजे का परीक्षण कर रहे हैं?

+0

SingleItem_ ** CodeCantBeModified ** – riezebosch

+0

@riezebosch: यदि पुश को धक्का देने के लिए आता है तो आप एक प्रॉक्सी ऑब्जेक्ट बना सकते हैं जो एक इंटरफेक्ट लागू करता है और केवल विधि कॉल के माध्यम से गुजरता है। यह इंटरफ़ेस को लागू करने के लिए कक्षा को प्राप्त करने के समान ही नहीं है लेकिन इसका एक ही प्रभाव है। – Chris

0

सामान्य रूप से, आप एक और स्तर का संकेत जोड़ सकते हैं।

  1. आसपास SingleItem_CodeCantBeModified
  2. एक आवरण कक्षा बनाएं इस आवरण IItem इंटरफ़ेस वारिस
  3. बनाओ SingleItemManagerSingleItem_CodeCantBeModified

या

के बजाय IItem पर निर्भर करते हैं, तो Increment एक आभासी विधि है (मैं समझता हूं कि यह आपके नमूना कोड में नहीं है, लेकिन बस मामले में), partial mocking का उपयोग करें।

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