c# - सी#में इकाई परीक्षण निजी तरीकों




unit-testing (6)

विजुअल स्टूडियो स्वचालित रूप से जेनरेट किए गए एक्सेसर क्लास के माध्यम से निजी तरीकों के यूनिट परीक्षण की अनुमति देता है। मैंने एक निजी विधि का परीक्षण लिखा है जो सफलतापूर्वक संकलित करता है, लेकिन यह रनटाइम पर विफल रहता है। कोड और परीक्षण का एक काफी न्यूनतम संस्करण है:

//in project MyProj
class TypeA
{
    private List<TypeB> myList = new List<TypeB>();

    private class TypeB
    {
        public TypeB()
        {
        }
    }

    public TypeA()
    {
    }

    private void MyFunc()
    {
        //processing of myList that changes state of instance
    }
}    

//in project TestMyProj           
public void MyFuncTest()
{
    TypeA_Accessor target = new TypeA_Accessor();
    //following line is the one that throws exception
    target.myList.Add(new TypeA_Accessor.TypeB());
    target.MyFunc();

    //check changed state of target
}

रनटाइम त्रुटि है:

Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.

इंटेलिजेंस के अनुसार - और इसलिए मुझे लगता है कि कंपाइलर - लक्ष्य टाइपए_एसेसर प्रकार है। लेकिन रनटाइम पर यह टाइपए टाइप प्रकार है, और इसलिए सूची जोड़ विफल हो जाती है।

क्या कोई तरीका है कि मैं इस त्रुटि को रोक सकता हूं? या, शायद अधिक संभावना है, अन्य लोगों के पास अन्य सलाह क्या है (मैं भविष्यवाणी करता हूं कि "निजी तरीकों का परीक्षण न करें" और "ऑब्जेक्ट परीक्षणों में वस्तुओं की स्थिति में हेरफेर नहीं है")।


"मानक या सर्वोत्तम अभ्यास के रूप में कुछ भी नहीं कहा जाता है, शायद वे सिर्फ लोकप्रिय राय हैं"।

इस चर्चा के लिए भी यही सच है।

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

यदि आप निजी तरीकों का आह्वान करना चाहते हैं तो आप "PrivateObject" कक्षा का उपयोग कर सकते हैं और इनवॉक विधि को कॉल कर सकते हैं। आप इस इंडिप यूट्यूब वीडियो ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ) देख सकते हैं जो दिखाता है कि "PrivateObject" का उपयोग कैसे करें और यह भी चर्चा करता है कि निजी तरीकों का परीक्षण तार्किक है या नहीं।


आप PrivateObject क्लास का उपयोग कर सकते हैं

Class target = new Class();
PrivateObject obj = new PrivateObject(target);
var retVal = obj.Invoke("PrivateMethod");
Assert.AreEqual(retVal, expectedVal);

निजी तरीकों का परीक्षण करने का एक तरीका प्रतिबिंब के माध्यम से है। यह न्यूटिट और एक्सयूनीट पर भी लागू होता है:

MyObject objUnderTest = new MyObject();
MethodInfo methodInfo = typeof(MyObject).GetMethod("SomePrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
object[] parameters = {"parameters here"};
methodInfo.Invoke(objUnderTest, parameters);

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


हां, निजी तरीकों का परीक्षण न करें .... इकाई परीक्षण का विचार इकाई को अपने सार्वजनिक 'एपीआई' द्वारा जांचना है।

यदि आपको लगता है कि आपको बहुत से निजी व्यवहार का परीक्षण करने की आवश्यकता है, तो संभवतया आपके पास उस कक्षा के भीतर छिपी हुई एक नई 'कक्षा' है जिसे आप परीक्षण करने की कोशिश कर रहे हैं, इसे निकालें और इसे अपने सार्वजनिक इंटरफ़ेस द्वारा परीक्षण करें।

सलाह / सोच उपकरण का एक टुकड़ा ..... एक विचार है कि कोई विधि कभी निजी नहीं होनी चाहिए। मतलब सभी विधियों को किसी ऑब्जेक्ट के सार्वजनिक इंटरफ़ेस पर रहना चाहिए .... यदि आपको लगता है कि आपको इसे निजी बनाने की आवश्यकता है, तो संभवतः यह किसी अन्य ऑब्जेक्ट पर रहता है।

सलाह का यह टुकड़ा अभ्यास में काफी काम नहीं करता है, लेकिन इसकी ज्यादातर अच्छी सलाह है, और अक्सर यह लोगों को अपनी वस्तुओं को छोटी वस्तुओं में विघटित करने के लिए प्रेरित करेगा।


टीएल; डीआर: उस वर्ग पर परीक्षण, दूसरी कक्षा में निजी विधि निकालें; एसआरपी सिद्धांत (एकल जिम्मेदारी सिद्धांत) के बारे में और पढ़ें

ऐसा लगता है कि आपको private विधि में किसी अन्य वर्ग में निकालने की आवश्यकता है; इसमें public होना चाहिए। private विधि पर परीक्षण करने की कोशिश करने के बजाय, आपको इस दूसरी कक्षा की public विधि का परीक्षण करना चाहिए।

हमारे पास निम्नलिखित परिदृश्य है:

Class A
+ outputFile: Stream
- _someLogic(arg1, arg2) 

हमें _someLogic के तर्क का परीक्षण करने की _someLogic ; लेकिन ऐसा लगता है कि Class A आवश्यकता से अधिक भूमिका निभाती है (एसआरपी सिद्धांत का उल्लंघन); बस दो वर्गों में refactor

Class A1
    + A1(logicHandler: A2) # take A2 for handle logic
    + outputFile: Stream
Class A2
    + someLogic(arg1, arg2) 

इस तरह कुछ someLogic ए 2 पर परीक्षण किया जा सकता है; ए 1 में बस कुछ नकली ए 2 बनाएं, फिर यह जांचने के लिए कि ए 2 को कुछ someLogic नामक फ़ंक्शन में बुलाया गया है, someLogic





unit-testing