У меня есть класс 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' дает мне пустой. Я затем попробовал:
[ClassInitialize]
public void InitialiseClass() {
var myService = new Mock<IMyService>();
MyService = myService.Object;
}
с 'MyService', объявленным как:
[Export(typeof(IMyService))]
public IMyService MyService { get; set; }
Но все еще никакая радость, я пропускаю что-то - это даже возможно?
Я использую SL3, Предварительный просмотр MEF 9 и MOQ.
Любая справка ценится!
Удачи
Chris
Ваш класс должен выглядеть так:
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 вступает в игру только при соединении многих компонентов вместе, что прямо противоположно тому, что происходит в модульном тесте. По определению, модульный тест - это тест компонента в отдельности.
Edit: если вы предпочитаете инъекцию свойств, то вашему классу не нужен конструктор, и организующая часть в вашем модульном тесте должна выглядеть так:
var myService = new Mock<IMyService>();
var a = new A();
a.MyService = myService.Object;
Где вы добавили [Export] к вашему экземпляру IMyService, добавили ли вы его в контейнер композиции? Если нет, то он не будет участвовать в композиции. Чтобы добавить объект в контейнер, сделайте следующее:
container.ComposeExportedValue<IMyService>(mock.Object);
Или просто:
container.ComposeExportedValue(mock.Object); // type inference.
Сделав это до создания экземпляра A, вы сможете компоновать его внутри вашего экземпляра A.
Вы не должны запускать MEF в своих модульных тестах. Композиция выходит за рамки модульного теста и не отличается от контейнера IoC.
Insted, вы должны ввести необходимые зависимости вручную:
[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());
}
}