2008-12-03 14 views
11

वर्तमान में मैं अपने यूनिट टेस्ट में मॉक ऑब्जेक्ट्स की अवधारणा को पेश करना शुरू कर रहा हूं। विशेष रूप से मैं Moq ढांचे का उपयोग कर रहा हूँ। हालांकि, मैंने जो कुछ देखा है, वह यह है कि अचानक इस कक्षा के उपयोग से परीक्षण करने वाले वर्ग 0% के कोड कवरेज दिखा रहे हैं।मैं अपने यूनिट परीक्षणों में नकली ऑब्जेक्ट्स का उपयोग कैसे कर सकता हूं और अभी भी कोड कवरेज का उपयोग कर सकता हूं?

अब मैं समझता हूं कि चूंकि मैं कक्षा का मज़ाक उड़ा रहा हूं, इसलिए यह वास्तविक वर्ग नहीं चला रहा है .... लेकिन मैं इन परीक्षणों को कैसे लिखूं और कोड कवरेज सटीक परिणाम लौटा सकता हूं? क्या मुझे परीक्षणों का एक सेट लिखना है जो मोक्स का उपयोग करता है और कक्षा को तुरंत चालू करने के लिए एक सेट का उपयोग करता है।

शायद मैं इसे महसूस किए बिना कुछ गलत कर रहा हूं?

यहाँ मुझे का एक उदाहरण यूनिट टेस्ट करने के लिए एक वर्ग "MyClass" कहा जाता है की कोशिश कर रहा है:

using Moq; 
using NUnitFramework; 

namespace MyNameSpace 
{ 
    [TestFixture] 
    public class MyClassTests 
    { 

     [Test] 
     public void TestGetSomeString() 
     { 
      const string EXPECTED_STRING = "Some String!"; 

      Mock<MyClass> myMock = new Mock<MyClass>(); 
      myMock.Expect(m => m.GetSomeString()).Returns(EXPECTED_STRING); 

      string someString = myMock.Object.GetSomeString(); 

      Assert.AreEqual(EXPECTED_STRING, someString); 
      myMock.VerifyAll(); 

     } 

    } 

    public class MyClass 
    { 
     public virtual string GetSomeString() 
     { 
      return "Hello World!"; 
     } 
    } 
} 

किसी को भी पता है कि मैं क्या अलग ढंग से करना चाहिए?

उत्तर

15

आप अपने नकली वस्तुओं का सही ढंग से उपयोग नहीं कर रहे हैं। जब आप नकली वस्तुओं का उपयोग कर रहे हैं तो आप परीक्षण करना चाहते थे कि वास्तव में वास्तविक वस्तुओं का उपयोग किए बिना आपका कोड अन्य वस्तुओं के साथ कैसे इंटरैक्ट करता है। नीचे दिए गए कोड देखें:

using Moq; 
using NUnitFramework; 

namespace MyNameSpace 
    { 
     [TestFixture] 
     public class MyClassTests 
     { 

      [Test] 
      public void TestGetSomeString() 
      { 
       const string EXPECTED_STRING = "Some String!"; 

       Mock<IDependance> myMock = new Mock<IDependance>(); 
       myMock.Expect(m => m.GiveMeAString()).Returns("Hello World"); 

       MyClass myobject = new MyClass(); 

       string someString = myobject.GetSomeString(myMock.Object); 

       Assert.AreEqual(EXPECTED_STRING, someString); 
       myMock.VerifyAll(); 

      } 

     } 

     public class MyClass 
     { 

      public virtual string GetSomeString(IDependance objectThatITalkTo) 
      { 
       return objectThatITalkTo.GiveMeAString(); 
      } 
     } 

     public interface IDependance 
     { 
      string GiveMeAString(); 
     } 
    } 

यह नहीं दिखता है जैसे कि यह कुछ भी उपयोगी कर रही है जब आपके कोड सिर्फ इसके पीछे किसी भी तर्क के बिना एक स्ट्रिंग लौटा रहा है।

वास्तविक शक्ति तब आती है जब आप GetSomeString() विधि कुछ तर्क करते हैं जो IDependdance से वापसी के आधार पर आउटपुट स्ट्रिंग के परिणाम को बदल सकता है। GiveMeAString() विधि, फिर आप देख सकते हैं कि आपकी विधि IDependdance इंटरफ़ेस से खराब डेटा कैसे भेजी जाती है।

कुछ की तरह:

public virtual string GetSomeString(IDependance objectThatITalkTo { 
    if (objectThatITalkTo.GiveMeAString() == "Hello World") 
    return "Hi"; 
} 

अब अगर आप अपने परीक्षण में इस लाइन है:

myMock.Expect(m => m.GiveMeAString()).Returns(null); 

अपने GetSomeString() विधि का क्या होगा?

+0

पैरामीटर के बाद आपके GetSomeString उदाहरण में एक ब्रैकेट गुम हो रहा है। –

6

बड़ी गलती System Under Test (एसयूटी) का मज़ाक उड़ा रही है, तो आप कुछ और परीक्षण करते हैं। आपको केवल निर्भर निर्भरता का नकल करना चाहिए।

0

इससे बहुत समझदारी होती है। मूलतः तुम कह रहे हो मैं निम्न कार्य करने की आवश्यकता है:

public class MyClass 
{ 
    public virtual string GetSomeString(MyOtherClass moc) 
    { 
     return moc.ToString(); 
    } 
} 

..... 

Mock<MyOtherClass> myMock = new Mock<MyOtherClass>(); 

MyClass mc = new MyClass(); 

string someString = mc.GetSomeString(myMock.Object); 
Assert.AreEqual(EXPECTED_STRING, someString); 

मूलतः SUT instantiating और केवल कक्षाओं SUT की आवश्यकता के लिए mocks का उपयोग कर?

+0

प्लस आपके GetSomeString विधि में अब कवरेज होगा क्योंकि आप असली GetSomeString को कॉल कर रहे हैं, लेकिन केवल एक नकली ऑब्जेक्ट के साथ इसकी आवश्यकता है ताकि आप किसी भी गहरे जा रहे हों और किसी भी मिसाइल को लॉन्च न करें जिसे आप नहीं जानते :) यह सब अलगाव में परीक्षण के बारे में है। –

2

मैं यहां तक ​​कि चल रहे इंटरैक्शन को समझने तक ढांचे के ढांचे से दूर रहने की सलाह दूंगा।

आईएमओ मैन्युअल रूप से बनाए गए परीक्षण युगल के साथ सीखना बेहतर है, फिर बाद में एक मॉकिंग फ्रेमवर्क के लिए स्नातक हो। मेरा तर्क:

  1. वास्तव में क्या हो रहा है, इस बारे में ढांचे को ढंकना; इंटरैक्शन को समझना आसान है यदि आपको अपनी निर्भरता स्पष्ट रूप से बनाना है, तो डीबगर में परीक्षणों का पालन करें।

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

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

परीक्षण युगल का उपयोग करने का कारण यह है कि यह परीक्षण के तहत कक्षा को अलग करता है, जिसका अर्थ है कि आप अपने कोड को अधिक नियंत्रित फैशन में प्रयोग कर सकते हैं।

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

आईई। प्रत्येक परीक्षण में, परीक्षण के तहत कक्षा की निर्भरता विशेष रूप से कोड के एक विशेष टुकड़े का उपयोग करने के लिए बनाई जाती है।

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

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