繁体   English   中英

使用 Moq 使用内部构造函数模拟类型

[英]Mocking a type with an internal constructor using Moq

我正在尝试从 Microsoft Sync Framework 模拟一个类。 它只有一个内部构造函数。 当我尝试以下操作时:

var fullEnumerationContextMock = new Mock<FullEnumerationContext>();

我收到此错误:

System.NotSupportedException: Parent 没有默认构造函数。 必须显式定义默认构造函数。

这是堆栈跟踪:

System.Reflection.Emit.TypeBuilder.DefineDefaultConstructorNoLock(MethodAttributes attributes) System.Reflection.Emit.TypeBuilder.DefineDefaultConstructor(MethodAttributes attributes) System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() Castle。 DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType() Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type[] interfaces, ProxyGenerationOptions options) Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options) Castle。 DynamicProxy.ProxyGenerator.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] 拦截器) Castle.DynamicProxy。 ProxyGenerator.Create ClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] 拦截器) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, IInterceptor[] 拦截器) Moq.Mock 1.<InitializeInstance>b__0() Moq.PexProtector.Invoke(Action action) Moq.Mock 1.InitializeInstance()

我该如何解决这个问题?

您不能模拟没有公共构造函数的类型,因为 Moq 将无法实例化该类型的对象。 根据您要测试的内容,您有以下几种选择:

  1. 如果有工厂对象或其他获取 FullEnumerationContext 实例的方法,也许您可​​以使用它(抱歉,我不熟悉同步框架)
  2. 您可以使用私有反射来实例化 FullEnumerationContext,但是您将无法在其上模拟方法。
  3. 您可以引入一个可模拟的接口和/或包装器对象,被测试的代码可以调用。 运行时实现将委托给真正的 FullEnumerationContext,而您的测试时实现将执行您需要的任何操作。

我不是真正的 Moq 专家,但我认为您需要为构造函数指定参数。 在 Rhino Mocks 中,您可以像这样指定它们:

var fullEnumerationContextMock = new Mock<FullEnumerationContext>(arg1, arg2);

在起订量中可能类似。

其实你可以。 打开您的 AssemblyInfo.cs 文件并在末尾添加以下行,

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

基于从答案marcind我创建了一个接口( IFullEnumerationContext ),我嘲笑,然后我有方法,我想的检验标准,采取的两个重载FullEnumerationContext ,另一个需要IFullEnumerationContext 感觉不是很好,但确实有效。 欢迎任何更好的建议或改进。

public override void EnumerateItems(FullEnumerationContext context)
{
    List<ItemFieldDictionary> listItemFieldDictionary = EnumerateItemsCommon();
    context.ReportItems(listItemFieldDictionary);
}

public void EnumerateItems(IFullEnumerationContext context)
{
    List<ItemFieldDictionary> listItemFieldDictionary = EnumerateItemsCommon();
    context.ReportItems(listItemFieldDictionary);
}

在您的被测系统项目中,您需要:

  • protected internal的 SUT 类中的protected internal构造函数可见性(例如FullEnumerationContext
  • AssemblyInfo.cs应该向测试项目公开它们的内部结构:

     [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM