Перемешивание типа с помощью внутреннего конструктора с использованием Moq - PullRequest
27 голосов
/ 19 июля 2010

Я пытаюсь смоделировать класс из 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.Elassy.Generators.ExyTypexy.Eterters.Aj.GenerateCode (интерфейсы Type [], параметры ProxyGenerationOptions) Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxy (тип classToProxy, тип [] AdditionalInterfacesToProxy, ProxyGenerationOptions параметры) Castle.DynamicProxy.ProxyGenerator.CoreProxyToppingToGextTOPTIPTOPTOPTOPTOPEO.DynamicProxy.ProxyGenerator.CreateClassProxy (Тип classToProxy, Тип [] AdditionalInterfacesToProxy, ProxyGenerationOptОпции ионов, Object [] constructorArguments, IInterceptor [] перехватчики) Castle.DynamicProxy.ProxyGenerator.CreateClassProxy (Тип classToProxy, Тип [] AdditionalInterfacesToProxy, ProxyGenerationOptions, IInterceptor [] перехватчики) Castle.DynamicProxy.ProreCateOgnate.ProxyGenerator] AdditionalInterfacesToProxy, IInterceptor [] перехватчики) Moq.Mock 1.<InitializeInstance>b__0() Moq.PexProtector.Invoke(Action action) Moq.Mock 1.InitializeInstance ()

Как мне обойти это?

Ответы [ 4 ]

20 голосов
/ 19 июля 2010

Вы не можете смоделировать тип, у которого нет открытого конструктора, потому что Moq не сможет создать экземпляр объекта этого типа.В зависимости от того, что вы пытаетесь протестировать, у вас есть несколько вариантов:

  1. Если есть фабричный объект или какой-то другой способ получения экземпляров FullEnumerationContext, возможно, вы можете использовать это (извините, я незнакомы с платформой синхронизации)
  2. Вы можете использовать частное отражение для создания экземпляра FullEnumerationContext, но тогда вы не сможете имитировать методы для него.
  3. Вы можете ввести интерфейс и / или оболочкуобъект, который высмеивается, что тестируемый код может вызвать.Реализация во время выполнения делегировала бы реальный FullEnumerationContext, в то время как ваша реализация во время тестирования будет выполнять любое необходимое действие.
4 голосов
/ 19 июля 2010

Я на самом деле не эксперт по Moq, но я думаю, что вам нужно указать аргументы для конструктора.В Rhino Mocks вы можете указать их так:

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

Вероятно, в Moq это похоже.

2 голосов
/ 20 июля 2010

Основываясь на ответах 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);
}
1 голос
/ 14 августа 2017

На самом деле вы можете. Откройте файл AssemblyInfo.cs и добавьте следующую строку в конце:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

...