You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#抽象类的internal/private方法单元测试出现TargetException如何解决?

错误根因

你触发报错的核心原因有两个:

  • 你给PrivateObject传入的第一个参数是Mock<MyAbstractClass>类型的包装对象,不是Moq生成的代理类实例,需要取.Object属性拿到实际的被代理对象
  • Moq生成的动态代理类是继承自MyAbstractClass的子类,你显式传入基类的PrivateType会触发类型匹配校验失败

解决方案

方案1:修正Moq调用代码(最小改动)

直接去掉多余的PrivateType参数,传入Moq生成的实际代理实例即可,修改后的测试代码如下:

public void MyTestMethod()
{
    var testProcessorMock = new Mock<MyAbstractClass>
    {
        CallBase = true
    };
    // 取实际的代理实例,而不是Mock包装对象
    var targetInstance = testProcessorMock.Object;
    // 直接用实例初始化PrivateObject,不需要传PrivateType
    PrivateObject privateObject = new PrivateObject(targetInstance);
    var resValue = (string)privateObject.Invoke("MyMethod");
    Assert.AreEqual(resValue ,"HI");
}

方案2:手动实现测试子类(更稳定,无Moq依赖问题)

如果你的抽象类没有未实现的抽象成员,直接写一个空的测试子类继承抽象类,避免动态代理的兼容问题:

// 测试项目内临时加的测试子类
public class TestMyAbstractClass : MyAbstractClass
{
    // 如果抽象类有抽象方法,在这里加空实现即可
}

对应的测试代码:

public void MyTestMethod()
{
    var targetInstance = new TestMyAbstractClass();
    PrivateObject privateObject = new PrivateObject(targetInstance);
    var resValue = (string)privateObject.Invoke("MyMethod");
    Assert.AreEqual(resValue ,"HI");
}

补充说明:Internal方法的测试简化方案

如果需要测试的是internal成员,不需要用反射,可以直接在原项目的AssemblyInfo.cs里加如下配置,把internal可见性授权给测试项目:

[assembly: InternalsVisibleTo("你的测试项目程序集名称")]

配置后可以在测试项目里直接调用internal方法,不需要依赖PrivateObject反射调用。

内容的提问来源于stack exchange,提问作者Joy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:30:04