代码之家  ›  专栏  ›  技术社区  ›  Gishu

如何替换MEF容器中导出的零件/对象?

  •  4
  • Gishu  · 技术社区  · 14 年前

    我有一个正在运行的WPF应用程序,它需要所有影响UI的操作都在UI线程上。WPF还提供了一个Dispatcher类来处理这个问题,所以我将其提取到一个依赖项中。

    public interface UIActionExecutor
        {
            void Do(Action action);
        }
    

    现在的问题是,在我的验收测试中,我需要替换容器中响应 UIActionExecutor 以嘲弄的方式。所以我需要移除 ExecutorUsingWpfDispatcher 从我的容器中添加 MockUIActionExecutor

    更新: 如果有人想知道为什么/如何解决-阅读 Glenn Block's blog post#2 . 这就是我最后用的

        var defaultExportProvider = new CatalogExportProvider(__defaultCatalog);
        var catalogOfMocks = new AssemblyCatalog(assemblyExportingMocks);
        // order of params important (precedence left to right)
        __container = new CompositionContainer(catalogOfMocks, defaultExportProvider);
        defaultExportProvider.SourceProvider = __container
    
    2 回复  |  直到 14 年前
        1
  •  7
  •   Wim Coenen    14 年前

    DI容器负责将所有内容连接在一起。

    单元测试负责独立地测试单个代码单元。mock用于替换依赖项。因此,原则上,在单元测试中不应该使用DI容器。它与“单元测试”的定义相矛盾()

    // first set up the main export provider
    var mainCatalog = new AggregateCatalog(...); 
    var mainExportProvider = new CatalogExportProvider(mainCatalog);
    
    // now set up a container with mocks
    var mockContainer = new CompositionContainer();
    mockContainer.ComposeExportedValue<IFoo>(fooMock);
    mockContainer.ComposeExportedValue<IBar>(barMock);
    
    // use this testContainer, it will give precedence to mocks when available
    var testContainer = new CompositionContainer(mockContainer, mainExportProvider);
    
    // link back to the testContainer so mainExportProvider picks up the mocks
    mainExportProvider.SourceProvider = testContainer;
    

    () 从你的博客来看,我相信你已经知道了。但是其他人也会读到这个答案,所以我想弄清楚“单元测试”这个词。

        2
  •  2
  •   CodeMonkey    12 年前

    无法使可接受的解决方案工作。以下代码应起作用,优先顺序在 AggregateExportProvider .

    var mainContainer = new CompostionContainer();
    mainContainer.ComposeExportedValue<IFoo>(new Foo() {Test = 1});
    
    var mockContainer = new CompositionContainer();            
    mockContainer.ComposeExportedValue<IFoo>(new Foo() {Test = 2});
    
    var aggregateExportProvider = new AggregateExportProvider(
         mockContainer,   // IFoo in this container takes precedence
         mainContainer);
    
    IFoo foo = aggregateExportProvider.GetExportedValue<IFoo>();
    
    Console.WriteLine(foo.Test); // Outputs: 2