MEF 进口起订量?

发布于 2024-09-08 15:14:07 字数 907 浏览 4 评论 0原文

我有一个 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。

任何帮助表示赞赏!

干杯

克里斯

I have a class A which has the following:

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

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

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

And a Test to test this (seperate Dll - obviously)

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

This fails as attempting to call 'MyService' gives me null.
I've then tried:

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

with 'MyService' declared as:

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

But still no joy, am I missing something - is this even possible?

I'm using SL3, MEF Preview 9 and MOQ.

Any help appreciated!

Cheers

Chris

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

停滞 2024-09-15 15:14:07

您的类应该如下所示:

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;

Your class should look like this:

public class A 
{
    private readonly IMyService _myService;

    [ImportingConstructor]
    public A(IMyService myService)
    {
        _myService = myService;
    }

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

And your test should look like this:

[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());
}

The fact that you use MEF should not be important in unit tests. MEF only comes into play when wiring many components together, which is exactly the opposite of what happens in a unit test. A unit test is by definition a test of a component in isolation.

Edit: if you prefer property injection, then your class doesn't need a constructor and the arrange part in your unit test should look like this instead:

    var myService = new Mock<IMyService>();
    var a = new A();
    a.MyService = myService.Object;
随遇而安 2024-09-15 15:14:07

您已将 [Export] 添加到 IMyService 实例中,您实际上是否已将其添加到组合容器中?如果不是,则不会参与合成。要将模拟对象添加到容器中,请执行以下操作:

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

或者只是:

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

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

Where you've added [Export] to your IMyService instance, have you actually added that to the composition container? If not, it won't take part in composition. To add a mocked object to the container, do the following:

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

Or just:

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

Doing this before you've created an instance of A will enable it to be composed inside your A instance.

秉烛思 2024-09-15 15:14:07

您不应该在单元测试中启动 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());
  }
}

You shouldn't be firing up MEF in your unit tests. Composition is way beyond unit test's scope, not dissimilar to an IoC container.

Insted, you should inject required dependencies manually:

[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());
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文