34

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

var fullEnumerationContextMock = new Mock<FullEnumerationContext>();

我收到此错误:

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

这是堆栈跟踪:

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.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] 拦截器) Castle.DynamicProxy .ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, IInterceptor[] 拦截器) Moq.MockDynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, IInterceptor[] 拦截器) Moq.MockDynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, IInterceptor[] 拦截器) Moq.Mock1.<InitializeInstance>b__0() Moq.PexProtector.Invoke(Action action) Moq.Mock1.初始化实例()

我该如何解决这个问题?

4

5 回答 5

23

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

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

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

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

起订量可能类似。

于 2010-07-19T09:17:08.527 回答
3

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

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

于 2017-08-14T11:09:57.193 回答
2

根据marcind的回答,我创建了一个接口 ( IFullEnumerationContext),我对其进行了模拟,然后我得到了我要测试的方法的两个重载,一个采用 the 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);
}
于 2010-07-20T12:30:45.130 回答
1

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

  • protected internalSUT 类中的构造函数可见性(例如FullEnumerationContext
  • AssemblyInfo.cs应该将它们的内部结构暴露给测试项目:

    [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
    
于 2019-12-04T19:41:10.033 回答