【问题标题】:Moq a MEF Import?最小起订量是 MEF 进口吗?
【发布时间】:2010-07-02 15:00:35
【问题描述】:

我有一个 A 类,它具有以下内容:

public class A {
    [Import(typeof(IMyService)]
    public IMyService MyService { get; set; }

    public A() {
        CompositionInitializer.SatisfyImports(this);
    }

    public void DoWork() {
        //Blah
        MyService.DoIt();
        //Blah
    }
}

还有一个测试来测试这个(单独的 Dll - 显然)

[TestMethod]
public void TestDoWork() {
    //Blah
    DoWork();
    //Assert assert
}

这失败了,因为尝试调用“MyService”给了我 null。 然后我尝试了:

[ClassInitialize]
public void InitialiseClass() {
    var myService = new Mock<IMyService>();
    MyService = myService.Object;
}

将“MyService”声明为:

[Export(typeof(IMyService))]
public IMyService MyService { get; set; }

但仍然没有喜悦,我错过了什么 - 这甚至可能吗?

我正在使用 SL3、MEF Preview 9 和 MOQ。

任何帮助表示赞赏!

干杯

克里斯

【问题讨论】:

    标签: c# silverlight moq mef


    【解决方案1】:

    你的班级应该是这样的:

    public class A 
    {
        private readonly IMyService _myService;
    
        [ImportingConstructor]
        public A(IMyService myService)
        {
            _myService = myService;
        }
    
        public void DoWork() {
            //Blah
            _myService.DoIt();
            //Blah
        }
    }
    

    你的测试应该是这样的:

    [TestMethod]
    public void DoWork_invokes_IMyService_DoIt() 
    {
        // arrange mock and system under test
        var myService = new Mock<IMyService>();
        var a = new A(myService.Object);
    
        // act    
        a.DoWork();
    
        // assert that DoIt() was invoked
        myService.Verify(x => x.DoIt());
    }
    

    您使用 MEF 的事实在单元测试中并不重要。 MEF 仅在将许多组件连接在一起时发挥作用,这与单元测试中发生的情况正好相反。根据定义,单元测试是对组件的独立测试。

    编辑:如果您更喜欢属性注入,那么您的类不需要构造函数,单元测试中的排列部分应如下所示:

        var myService = new Mock<IMyService>();
        var a = new A();
        a.MyService = myService.Object;
    

    【讨论】:

    • 好的,但是为什么我需要使用构造函数导入器,该属性在我的实际实现中工作正常,大概有一个路由可以模拟这些类型的导入?
    • @Chris:虽然 MEF 鼓励属性注入,但我更喜欢构造注入,因为这样编译器会阻止您创建缺少依赖项的对象。它还允许您将依赖项字段设置为只读,因此您不必考虑替换依赖项会发生什么。
    • 我选择了这种方法,我个人还是想知道你是否可以模拟属性注入,但这有助于解决我遇到的问题。干杯。
    • 我认为您已经假设该属性具有公共设置器。其中,如果您要注入,则不需要公共设置器。例如,我有一个演示者被注入它的视图,反之亦然。演示者封装了视图,因此没有公共设置器。与视图相同,它的演示者被注入并且没有公共设置器。
    • @IAbstract:根据定义,注入点应该是公开的。如果没有,您将依赖容器魔法来填充组件的依赖项。当您需要在容器之外(例如单元测试)或使用不支持该功能的不同容器重用该组件时,这将导致问题。当您构建一个可重用的组件库并且您无法控制使用该库的不同应用程序时,这些事情变得显而易见。
    【解决方案2】:

    您已将 [Export] 添加到 IMyService 实例的位置,您是否真的将其添加到组合容器中?如果没有,它就不会参与作曲。要将模拟对象添加到容器中,请执行以下操作:

     container.ComposeExportedValue<IMyService>(mock.Object);
    

    或者只是:

    container.ComposeExportedValue(mock.Object); // type inference.
    

    在您创建 A 的实例之前执行此操作将使其能够在您的 A 实例中组合。

    【讨论】:

    • 我不需要将具体实现添加到容器中即可使其工作。但我明白你的意思。你在哪里看到容器?
    【解决方案3】:

    您不应该在单元测试中启动 MEF。组合远远超出了单元测试的范围,与 IoC 容器没有什么不同。

    已安装,您应该手动注入所需的依赖项:

    [TestClass]
    public class ATest {
      Mock<IMyService> myService ;
      [TestInitialize]
      public void InitialiseClass() {
        myService = new Mock<IMyService>();
      }
    
      [TestMethod]
      public void DoWorkShouldCallDoIt {
        A a = new A();
        a.MyService = myService.Object;
        a.DoWork();
        myService.Verify(m=>m.DoIt(), Times.Once());
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-22
      • 2017-03-21
      • 1970-01-01
      • 2013-10-26
      • 2012-08-09
      • 2017-10-26
      相关资源
      最近更新 更多