2016-12-12 230 views
0

我有一个ViewModel,它在初始化时创建一个对象列表。这些对象是通过解析来自IoC的接口实现而创建的。我应该如何测试?

视图模型

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

单元测试

[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。DK/2010/02/03/ServiceLocatorisanAnti-模式/)? – 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

但后来我将如何修改我的视图模型的构造函数,这样我可以初始化列表,换句话说,使其可测试?

您与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); 
0:单元测试项目,你在同一个界面的其他一些实行通

您需要通过一种可以让您的测试通过的方式来实现这个“TestHardware”类。使用模拟框架将很有用。请参考以下链接,了解更多有关这一点:http://codetunnel.io/what-is-a-mocking-framework-why-is-it-useful/

+0

感谢您的阐述。我有点知道该怎么做,但不知道该怎么做。我认为[this](http://stackoverflow.com/questions/7816769/injecting-an-ienumerable-into-a-constructor-with-a-ninject-factory-method)会带给我我需要做的事情。 – Marshal

相关问题