Как смоделировать MEF ExportFactory <TGeneric>, используя экземпляры Moq? - PullRequest
0 голосов
/ 19 ноября 2018

Как я могу смоделировать импорт Managed Extensibility Framework (MEF) в ExportFactory [IMyType [T]] , используя макеты IMyType [T] (который сам по себе является универсальным интерфейсом )? Или, вообще, укажите экземпляры, которые должны быть возвращены ExportFactory, который не может быть создан одним конструктором?

Насколько мне известно, Moq не может создать макет напрямую. Мне нужна альтернатива реализации всего интерфейса, который может быть намного больше и изменяться, но я не хочу менять тест.

Однажды я обнаружил очень сложный код ExportProvider со строками ключ-значение, который не работал, если универсальный тип ExportFactory [T] сам по себе был универсальным.

Изменить: Оказалось, что в существующем коде используются строки имен контрактов, сгенерированные из type.FullName. Это было хорошо для не-дженериков, но у дженериков другой синтаксис имени. Код, с которым я работал, уже имеет довольно сложный класс, производный от ExportProvider и переопределяющий некоторые оригинальные методы, что позволяет фабрике возвращать экземпляры Moq mock.Object. На самом деле это всегда один и тот же экземпляр, а не фабрика. Смотрите также этот вопрос на CodeReview: https://codereview.stackexchange.com/questions/208550/retrieve-generic-contract-names-for-managed-extensibility-framework

// actual generic type is meaningless here, but it is a generic interface
public interface IMyType<T>
{
    string GetMessage();
}

public class FactoryImporter<T>
{
    [Import]
    ExportFactory<IMyType<T>> MyTypeFactory {get;set;}
} 

public class Tester
{
    public void TestFactoryImporter()
    {
        Func<IMyType<string>> createMockFunc = () =>
        {
            var mock = new Mock<IMyType<string>>();
            mock.Setup(m => m.GetMessage()).Returns("I'm a mocked IMyType<string>");
            return mock.Object;
        }

        var regBuilder = new RegistrationBuilder();

        // pseudo-code, how to do this in reality?
        regBuilder.ForType<IMyType<string>>().CreateInstance(createMockFunc);

        var catalog = new AggregateCatalog();
        var appCatalog = new ApplicationCatalog(regBuilder);
        catalog.Catalogs.Add(appCatalog);
        var container = new CompositionContainer(catalog);

        var factoryImporter = new FactoryImporter<string>();
        container.ComposeParts(factoryImporter);

        Assert.AreEqual(
            "I'm a mocked IMyType<string>",
            factoryImporter.MyTypeFactory.GetExport().Value.GetMessage());
    }
}
...