如何在 C# 中对抽象类中的内部方法或私有方法进行单元测试?

Joy*_*Joy 5 c# reflection

我必须为 C# 中的抽象类中的内部或私有方法编写单元测试。考虑一下:

Public Abstract Class MyAbstractClass
{
 Private String MyMethod()
 {
   //Do Something
   return "HI";
 }
}
Run Code Online (Sandbox Code Playgroud)

还有,我的测试方法:

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");
}
Run Code Online (Sandbox Code Playgroud)

但是当我运行测试方法时,出现以下错误:

 System.Reflection.TargetException: Object does not match target type.
Run Code Online (Sandbox Code Playgroud)

怎么解决呢?

lid*_*dqy 2

假设您使用Moq作为模拟工具,异常显示的结果是通过testProcessor而不是testProcessor.Object. 如果您将该行更改为...

PrivateObject privateObject = new PrivateObject(testProcessor.Object, privateType);
Run Code Online (Sandbox Code Playgroud)

...你将摆脱这个错误。
这就是它应该如何工作(在 NET Framework 中,PrivateObject 等尚未移植到 NET Core MSTest):

//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");
        }
    }
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我不知道抽象类的模拟会执行抽象类的实现。我认为它会创建返回默认值的存根,就像接口的模拟一样。
有趣的功能...