Moq a MEF Импорт? - PullRequest
       29

Moq a MEF Импорт?

6 голосов
/ 02 июля 2010

У меня есть класс А, который имеет следующее:

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' дает мне ноль. Я тогда попробовал:

[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.

Любая помощь приветствуется!

Приветствия

Chris

Ответы [ 3 ]

5 голосов
/ 03 июля 2010

Ваш класс должен выглядеть так:

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;
1 голос
/ 02 июля 2010

Где вы добавили [Export] к своему экземпляру IMyService, действительно ли вы добавили его в составной контейнер?Если нет, он не будет участвовать в композиции.Чтобы добавить макетированный объект в контейнер, выполните следующие действия:

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

Или просто:

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

Выполнение этого перед созданием экземпляра A позволит ему бытьсоставлено внутри вашего экземпляра.

0 голосов
/ 05 июля 2010

Вы не должны запускать 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());
  }
}
...