Издевательский тип с внутренним конструктором с использованием Moq
Я пытаюсь высмеять класс из Microsoft Sync Framework. Он имеет только внутренний конструктор. Когда я попробую следующее:
var fullEnumerationContextMock = new Mock<FullEnumerationContext>();
Я получаю эту ошибку:
System.NotSupportedException: родительский не имеет конструктора по умолчанию. Конструктор по умолчанию должен быть явно определен.
Это трассировка стека:
System.Reflection.Emit.TypeBuilder.DefineDefaultConstructorNoLock(MethodAttributes атрибуты) System.Reflection.Emit.TypeBuilder.DefineDefaultConstructor(MethodAttributes атрибуты) System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() System.Reflection.Emit.TypeBuilder.CreateType() Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType() Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(тип [] интерфейсы, параметры ProxyGenerationOptions) Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxy(Тип classToProxy, Тип [] дополнительныеИнтерфейсыToProxy, Параметры ProxyGenerationOptions) Castle.DynamicProxy.ProxyGenerator.CreateClassProxyType(Тип classToProxy, Тип [] AdditionalInterfacesToProxy, Параметры ProxyGenerationOptions) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Тип classToProxy, Тип [] дополнительныеИнтерфейсыToProxy, Параметры ProxyGenerationOptions, Object [] constructorArguments, IInterceptor [] перехватчики) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Тип classToProxy, Тип [] дополнительныеИнтерфейсыToProxy, Параметры ProxyGenerationOptions, IInterceptor [] перехватчики) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Тип classToProxy, Тип [] extraInterfacesToProxy, IInterceptor [] перехватчики) Moq.Mock 1.<InitializeInstance>b__0()
Moq.PexProtector.Invoke(Action action)
Moq.Mock
1.InitializeInstance()
Как я могу обойти это?
Ответы
Ответ 1
Вы не можете высмеивать тип, не имеющий общего конструктора, потому что Moq не сможет создать экземпляр объекта такого типа. В зависимости от того, что вы пытаетесь протестировать, у вас есть несколько вариантов:
- Если есть объект factory или какой-либо другой способ получения экземпляров FullEnumerationContext, возможно, вы можете использовать это (извините, я не знаком с инфраструктурой синхронизации)
- Вы можете использовать частное отражение для создания экземпляра FullEnumerationContext, но тогда вы не сможете имитировать методы.
- Вы можете ввести интерфейс и/или объект-обертку, который будет выкачать, что вызванный код может вызвать. Реализация времени выполнения будет делегировать реальный FullEnumerationContext, в то время как ваша реализация времени выполнения будет выполнять любые действия, которые вам нужны.
Ответ 2
Я не эксперт по Moq, но я думаю, вам нужно указать аргументы для конструктора. В Rhino Mocks вы должны указать их следующим образом:
var fullEnumerationContextMock = new Mock<FullEnumerationContext>(arg1, arg2);
Вероятно, это похоже на Moq.
Ответ 3
Основываясь на ответах 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);
}
Ответ 4
Собственно, вы можете. Откройте файл AssemblyInfo.cs и добавьте следующую строку в конец,
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]