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
相关产品推荐
相关产品推荐

