मुझे सी # में एक अमूर्त वर्ग में एक आंतरिक या निजी विधि के लिए एक इकाई परीक्षण लिखना है। इस पर विचार करो:

Public Abstract Class MyAbstractClass
{
 Private String MyMethod()
 {
   //Do Something
   return "HI";
 }
}

और, मेरी परीक्षण विधि:

public void MyTestMethod()
{
    var testProcessor = new Mock<MyAbstractClass>
    {
        CallBase = true
    };
    var privateType = new PrivateType(typeof(MyAbstractClass));
    PrivateObject privateObject = new PrivateObject(testProcessor , privateType);
    var resValue = (String)privateObject.Invoke("MyMethod");
    Assert.AreEqual(resValue ,"HI");
}

लेकिन जब मैं परीक्षण विधि चलाता हूं, तो मुझे नीचे त्रुटि मिल रही है:

 System.Reflection.TargetException: Object does not match target type.

इसका समाधान कैसे करें?

3
Joy 4 सितंबर 2021, 05:23

3 जवाब

सबसे बढ़िया उत्तर

यह मानते हुए कि आप Moq को एक मॉकिंग टूल के रूप में उपयोग कर रहे हैं, अपवाद ने testProcessor.Object के बजाय >testProcessor। यदि आप उस लाइन को बदलते हैं ...

PrivateObject privateObject = new PrivateObject(testProcessor.Object, privateType);

...आप इस त्रुटि से छुटकारा पा लेंगे।
इस तरह इसे काम करना चाहिए (नेट फ्रेमवर्क में, PrivateObject और इस तरह नेट कोर एमएसटीएस्ट में पोर्ट नहीं किया गया है):

//productive code
    public abstract class MyAbstractClass
    {
        private string MyMethod()
        {
            //Do Something
            return "HI";
        }
    }

    //testproject

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var testProcessor         = new Moq.Mock<MyAbstractClass>();
            var privateType           = new PrivateType(typeof(MyAbstractClass));
            var privateObject         = new PrivateObject(testProcessor.Object, privateType);
            var resValue              = (string)privateObject.Invoke("MyMethod");
            Assert.AreEqual(resValue, "HI");
        }
    }

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

1
lidqy 4 सितंबर 2021, 09:26

आपको निजी तरीकों का परीक्षण नहीं करना चाहिए:

मैं निजी तरीकों का परीक्षण नहीं करता। एक निजी विधि एक कार्यान्वयन विवरण है जिसे कक्षा के उपयोगकर्ताओं के लिए छिपाया जाना चाहिए। निजी तरीकों का परीक्षण करने से एनकैप्सुलेशन टूट जाता है।

अधिक विवरण के लिए यह पोस्ट देखें।

जैसा कि फ्लाईडॉग 57 कहता है, आपको एक व्युत्पन्न वर्ग का परीक्षण करना चाहिए (सार नहीं)।

आप अपनी टेस्ट क्लास के अंदर एक प्राइवेट टेस्ट क्लास बनाकर इसे आसानी से कर सकते हैं और अपने टेस्ट में इस प्राइवेट क्लास का इस्तेमाल कर सकते हैं।

private class MyConcreteTestClass : MyAbstractClass 
{
     public string SomeMethodThatCallsMethodInAbstractClass()
     {
          ....
     }
}

public void MyTestMethod()
{
    // Arrange
    var testProcessor = new MyConcreteTestClass();

    // Act
    var result = testProcessor.SomeMethodThatCallsMethodInAbstractClass();

    // Asset
    Assert.AreEqual(result ,"HI");
}
3
openshac 4 सितंबर 2021, 04:14

निजी विधि खोजने के लिए आपको BindingFlags को NonPublic के रूप में निर्दिष्ट करना होगा।

मुझे यकीन नहीं है कि PrivateObject क्या है, लेकिन यह काम करना चाहिए (आप इसे अपनी आवश्यकताओं के लिए उपयुक्त बनाने के लिए इसे थोड़ा बदल सकते हैं):

Type type = typeof(MyAbstractClass);

MethodInfo method = type.GetMethod(
    methodName, BindingFlags.NonPublic | BindingFlags.Instance);

string result = (string)method.Invoke("MyMethod", null);
0
Misha Zaslavsky 4 सितंबर 2021, 03:12