[英]Mocking a type with an internal constructor using Moq
I'm trying to mock a class from the Microsoft Sync Framework.我正在尝试从 Microsoft Sync Framework 模拟一个类。 It only has an internal constructor.
它只有一个内部构造函数。 When I try the following:
当我尝试以下操作时:
var fullEnumerationContextMock = new Mock<FullEnumerationContext>();
I get this error:我收到此错误:
System.NotSupportedException: Parent does not have a default constructor.
System.NotSupportedException: Parent 没有默认构造函数。 The default constructor must be explicitly defined.
必须显式定义默认构造函数。
This is the stack trace:这是堆栈跟踪:
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[] interceptors) Castle.DynamicProxy.ProxyGenerator.Create
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[] interceptors) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, IInterceptor[] interceptors) Moq.Mock
1.<InitializeInstance>b__0() Moq.PexProtector.Invoke(Action action) Moq.Mock
1.InitializeInstance()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()
How can I work round this?我该如何解决这个问题?
You cannot mock a type that does not have a public constructor because Moq will not be able to instantiate an object of that type.您不能模拟没有公共构造函数的类型,因为 Moq 将无法实例化该类型的对象。 Depending on what you are trying to test, you have a few options:
根据您要测试的内容,您有以下几种选择:
I am not really an expert on Moq, but I think you need to specify the arguments for the constructor.我不是真正的 Moq 专家,但我认为您需要为构造函数指定参数。 In Rhino Mocks you would specify them like this:
在 Rhino Mocks 中,您可以像这样指定它们:
var fullEnumerationContextMock = new Mock<FullEnumerationContext>(arg1, arg2);
It is probably similar in Moq.在起订量中可能类似。
Actually you can.其实你可以。 Open your AssemblyInfo.cs file and add the following line at end,
打开您的 AssemblyInfo.cs 文件并在末尾添加以下行,
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
Based on the answers from marcind I've created an interface ( IFullEnumerationContext
) which I mock and then I've got two overloads of the method I am trying to test, one that takes the FullEnumerationContext
and another that takes IFullEnumerationContext
.基于从答案marcind我创建了一个接口(
IFullEnumerationContext
),我嘲笑,然后我有方法,我想的检验标准,采取的两个重载FullEnumerationContext
,另一个需要IFullEnumerationContext
。 It doesn't feel great, but it does work.感觉不是很好,但确实有效。 Any better suggestions or improvements would be welcome.
欢迎任何更好的建议或改进。
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);
}
In your System Under Test project you need:在您的被测系统项目中,您需要:
protected internal
constructor visibility in your SUT class (eg FullEnumerationContext
) protected internal
的 SUT 类中的protected internal
构造函数可见性(例如FullEnumerationContext
) AssemblyInfo.cs
should expose their internals to the test project: AssemblyInfo.cs
应该向测试项目公开它们的内部结构:
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.