2016-12-12 7 views
0

У меня есть ViewModel, который при инициализации создает список объектов. Эти объекты создаются путем разрешения реализации интерфейса из IoC.Как я должен проверить это?

ViewModel

public class ApplianceViewModel : IAppliance 
    { 
     private List<IHardware> HardwareItems {get; set;} 

     public ApplianceViewModel() 
     { 
      HardwareItems = new List<IHardware>(); 
      var hardware1 = Constants.Kernel.Get<IHardware>(); 
      var hardware2 = Constants.Kernel.Get<IHardware>(); 

      HardwareItems.Add(hardware1); 
      HardwareItems.Add(hardware2);   
     } 
    } 

Test Unit

[TestClass] 
public class ApplicanceViewModelTest 
{ 
    [TestMethod] 
    public void TestSomething() 
    { 
     //Arrange 
     var appliance = new ApplianceViewModel(); //This would fail to construct 

    } 
} 

выше инициализация потерпит неудачу как kernel будет нулевым. В основном, он говорит мне, что наличие постоянного класса и доступ к ядру напрямую - плохой дизайн.

Но как бы мне изменить свой конструктор viewmodel, чтобы я мог инициализировать список, другими словами, сделать его пригодным для тестирования?

спасибо.

+4

Не было бы лучше использовать IoC с DI вместо [антивируса локатора обслуживания] (http: //blog.ploeh.дк/2010/02/03/ServiceLocatorisanAnti-Pattern /)? – YuvShap

+0

@SomeUser: Да, я считаю, что шаблон ServiceLocator вредит мне, но вопрос в моем уме заключался в том, как его переписать? Затем я нашел [это решение] (http://stackoverflow.com/questions/7816769/injecting-an-ienumerable-into-a-constructor-with-a-ninject-factory-method), который, я думаю, разрешил бы проблему У меня есть. – Marshal

ответ

0

У вас может быть другой интерфейс, то есть IHardwareStuff, который вернет список объектов IHardware. IHardwareStuff передается в качестве аргумента в конструктор вашего ViewModel. Он разрешен контейнером инъекции зависимостей, и вы можете ввести тестовую реализацию, когда захотите.

Делая это разделение, вы разделите ваш объект в объект на значение и объектслужбы. Первый, который вы создаете, выполнив new и передав ему некоторые конкретные значения. Последний создается контейнером инъекции зависимостей и не имеет конкретных значений, переданных ему как конструктор.

Вы можете написать модульные тесты для обоих объектов.

0

Для хорошего и проверяемого дизайна лучше, если конструкторы ничего не делают, валидация или назначение переменной.

Я предлагаю ввести в конструктор ApplianceViewModel список HardwareItems.

1

Но как я могу изменить конструктор моего viewmodel, чтобы я мог инициализировать список, другими словами сделать его пригодным для проверки?

Вы впрыснуть его реализаций интерфейса IHardware:

public class ApplianceViewModel : IAppliance 
{ 
    private List<IHardware> HardwareItems {get; set;} 

    public ApplianceViewModel(IHardware hardware1, Hardware hardware2) 
    { 
     HardwareItems = new List<IHardware>(); 
     var hardware1 = hardware1; 
     var hardware2 = hardware2; 

     HardwareItems.Add(hardware1); 
     HardwareItems.Add(hardware2);   
    } 
} 

Так во время выполнения можно впрыснуть модель вида с существующими константами:

var appliance = new ApplianceViewModel(Constants.Kernel.Get<IHardware>(), Constants.Kernel.Get<IHardware>()); 

... и в вашем единичный тестовый проект, который вы передаете в какой-то другой реализации одного и того же интерфейса:

IHardware testHardware = new TestHardware(); 
var appliance = new ApplianceViewModel(testHardware, testHardware); 

Вам необходимо реализовать этот класс «TestHardware» таким образом, чтобы ваш тест проходил. Использование фальшивой структуры будет полезно. Дополнительную информацию можно найти по следующей ссылке: http://codetunnel.io/what-is-a-mocking-framework-why-is-it-useful/

+0

Спасибо за уточнение. Я как бы знал, что делать, но не как это сделать. Я думаю, что [это] (http://stackoverflow.com/questions/7816769/injecting-an-ienumerable-into-a-constructor-with-a-ninject-factory-method) потребует от меня того, что мне нужно сделать. – Marshal