unit-testing - नकल - पेपर में चीटिंग करने के तरीके




आप एक सील वर्ग का मज़ाक कैसे उड़ाते हैं? (7)

मोक्ड सीलिंग क्लासेस में काफी दर्द हो सकता है। मैं वर्तमान में इसे संभालने के लिए एक एडेप्टर पैटर्न का पक्ष ले रहा हूं, लेकिन इसके बारे में कुछ अजीब लगता है।

तो, आप सील की गई कक्षाओं का सबसे अच्छा तरीका क्या है?

जावा के जवाब स्वागत से अधिक हैं । वास्तव में, मैं यह अनुमान लगाऊंगा कि जावा समुदाय इस समय के साथ काम कर रहा है और इसमें बहुत कुछ है।

लेकिन यहां कुछ .NET राय दी गई हैं:


.NET के लिए, आप TypeMock जैसी किसी चीज़ का उपयोग कर सकते हैं, जो प्रोफाइलिंग API का उपयोग करता है और आपको लगभग कुछ भी कॉल करने की अनुमति देता है।


एक मोहरबंद वर्ग का मजाक उड़ाना पूरी तरह से उचित है क्योंकि कई रूपरेखा वर्ग सील हैं।

मेरे मामले में मैं .Net के MessageQueue वर्ग का मजाक उड़ाने की कोशिश कर रहा हूं ताकि मैं अपने सुंदर अपवाद से निपटने वाले तर्क TDD कर सकूं।

अगर किसी के पास "गैर-अति-योग्य सदस्य पर अमान्य सेटअप" के बारे में Moq की त्रुटि को दूर करने के बारे में विचार हैं, तो कृपया मुझे बताएं।

कोड:

    [TestMethod]
    public void Test()
    {
        Queue<Message> messages = new Queue<Message>();
        Action<Message> sendDelegate = msg => messages.Enqueue(msg);
        Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate =
            (v1, v2) =>
            {
                throw new Exception("Test Exception to simulate a failed queue read.");
            };

        MessageQueue mockQueue = QueueMonitorHelper.MockQueue(sendDelegate, receiveDelegate).Object;
    }
    public static Mock<MessageQueue> MockQueue
                (Action<Message> sendDelegate, Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate)
    {
        Mock<MessageQueue> mockQueue = new Mock<MessageQueue>(MockBehavior.Strict);

        Expression<Action<MessageQueue>> sendMock = (msmq) => msmq.Send(It.IsAny<Message>()); //message => messages.Enqueue(message);
        mockQueue.Setup(sendMock).Callback<Message>(sendDelegate);

        Expression<Func<MessageQueue, Message>> receiveMock = (msmq) => msmq.Receive(It.IsAny<TimeSpan>(), It.IsAny<MessageQueueTransaction>());
        mockQueue.Setup(receiveMock).Returns<TimeSpan, MessageQueueTransaction>(receiveDelegate);

        return mockQueue;
    }

टाइपमॉक के साथ समस्या यह है कि यह खराब डिजाइन का बहाना करता है। अब, मुझे पता है कि यह अक्सर किसी और की खराब डिजाइन है जिसे यह छिपा रहा है, लेकिन इसे अपने विकास की प्रक्रिया में अनुमति देने से आपके खुद के खराब डिजाइनों को अनुमति देने में बहुत आसानी हो सकती है।

मुझे लगता है कि यदि आप एक मॉकिंग फ्रेमवर्क का उपयोग करने जा रहे हैं, तो आपको एक पारंपरिक (जैसे Moq) का उपयोग करना चाहिए और एक अमूर्त चीज के चारों ओर एक आइसोलेशन लेयर बनाएं, और इसके बजाय आइसोलेशन लेयर को मॉक करें।


मुझे हाल ही में यह समस्या आई और वेब पढ़ने / खोज करने के बाद, ऐसा लगता है कि जैसा कि ऊपर वर्णित एक अन्य टूल का उपयोग करने के अलावा कोई आसान तरीका नहीं है। या चीजों को संभालने का क्रूड जैसा मैंने किया:

  • निर्माता को बुलाए बिना सील किए गए वर्ग का उदाहरण बनाएं।
  • System.Runtime.Serialization.FormatterServices.GetUninitializedObject (instanceType);

  • प्रतिबिंब के माध्यम से अपने गुणों / क्षेत्रों के लिए मान निर्दिष्ट करें

  • YourObject.GetType ()। GetProperty ("PropertyName")। SetValue (dto, newValue, null);
  • YourObject.GetType ()। GetField ("FieldName")। SetValue (dto, newValue);

मेरे अंगूठे का सामान्य नियम यह है कि जिन वस्तुओं को मॉक करने की आवश्यकता है, उनका एक सामान्य इंटरफ़ेस भी होना चाहिए। मुझे लगता है कि यह सही डिज़ाइन-वार है और परीक्षणों को बहुत आसान बनाता है (और आमतौर पर आपको वही मिलता है जो आप TDD करते हैं)। इसके बारे में Google परीक्षण ब्लॉग नवीनतम पोस्ट (बिंदु 9 देखें) में पढ़ा जा सकता है।

इसके अलावा, मैं पिछले 4 वर्षों में मुख्य रूप से जावा में काम कर रहा हूं और मैं कह सकता हूं कि मैंने एक बार एक अंतिम (सील) वर्ग बनाया है, जिस पर मैं गिन सकता हूं। यहां एक और नियम यह है कि मुझे हमेशा एक कक्षा को सील करने का एक अच्छा कारण होना चाहिए, क्योंकि यह डिफ़ॉल्ट रूप से सील करने का विरोध करता है।


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

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

आपके द्वारा संदर्भित लेख में दिए गए नमूने की तुलना में कोड कुछ अधिक परिष्कृत है, क्योंकि यह एक विधानसभा (स्रोत कोड के बजाय) का उत्पादन करता है, कोड पीढ़ी को किसी भी प्रकार पर प्रदर्शन करने की अनुमति देता है, और इसके लिए अधिक कॉन्फ़िगरेशन की आवश्यकता नहीं होती है।

अधिक जानकारी के लिए, कृपया इस पृष्ठ को देखें।


हालाँकि यह वर्तमान में केवल बीटा रिलीज़ में उपलब्ध है, मुझे लगता है कि यह नए फेक फ्रेमवर्क ( विजुअल स्टूडियो 11 बीटा रिलीज़ का हिस्सा) की shim फ़ीचर को ध्यान में रखते हुए सार्थक है।

शिम प्रकार उपयोगकर्ता परिभाषित प्रतिनिधि को किसी भी .NET विधि को अलग करने के लिए एक तंत्र प्रदान करते हैं। फॉक्स जनरेटर द्वारा शिम प्रकार कोड-जनरेट किए जाते हैं, और वे नए विधि कार्यान्वयन को निर्दिष्ट करने के लिए प्रतिनिधियों का उपयोग करते हैं, जिसे हम शिम प्रकार कहते हैं। हुड के तहत, शिम प्रकार कॉलबैक का उपयोग करते हैं जो कि विधि MSIL निकायों में रनटाइम पर इंजेक्ट किए गए थे।

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





mocking