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




unit-testing (7)

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

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

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

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

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

//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 क्लास का उपयोग कर सकते हैं

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

आप कक्षा के चारों ओर एक रैपर वर्ग बना सकते हैं जिसमें निजी विधि शामिल है जिसे आप परीक्षण करना चाहते हैं। इस रैपर वर्ग में एक सार्वजनिक विधि है जिसे Call_MyPrivateFunction कहा जाता है और जो बदले में अपनी बेस क्लास के निजी फ़ंक्शन को कॉल करता है।

कृपया ध्यान दें कि विधि वर्ग का एक्सेस स्तर [संरक्षित] में बदल जाएगा

कोड उदाहरण:

public class Order
{
    public int Quantity { get; set; }

    protected bool OrderIsBig ()
    {
        //This is the method we want to test. It needs to be protected in stead of private. Else... no cigar
        return Quantity > 100;
    }
}

//Use this wrapper class in your unit test.
public class FakeOrder : Order
{

    public bool Call_OrderIsBig()
    {
        //This makes the actual call to the protected method "OrderIsBig"
        return OrderIsBig();
    }
}

इकाई परीक्षण कोड इस तरह दिख सकता है:

FakeOrder order = new FakeOrder();
order.Quantity = 200;

bool isBig = order.Call_OrderIsBig();   //Make a call to a public method of the FakeOrder class which in turn makes a call to the protected method.

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

ऐसा लगता है कि आपको 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


वीएस 2005/2008 में आप निजी सदस्य का परीक्षण करने के लिए निजी एक्सेसर का उपयोग कर सकते हैं, लेकिन इस तरह वीएस के बाद के संस्करण में गायब हो गया था


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

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

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

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

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

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





unit-testing