2016-12-12 152 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

相關問題