2011-09-17 72 views
1

我使用設法和DI /嘲笑(Ninject/MOQ)我的頭輪單元測試中注入產品倉庫到我的控制器,我再通過定義無參數的構造函數到我的視圖模型,以允許測試。ASP.NET MVC Ninject/DI - 此對象

這是偉大的工作,並讓我的單元測試控制器動作和視圖模型。然而,當我運行該應用程序我得到「此對象定義無參數的構造函數」 ......現在我知道這是由於控制器試圖初始化它沒有參數的構造函數視圖模型。

我可以創建構造函數,並從該打電話給我具體的存儲庫(所以單元測試仍採用注射/嘲笑一個)。

這是正確的方法嗎?任何建議將不勝感激!

控制器:

public class ProductsController : Controller 
{ 
    private readonly IProductRepository productRepository; 

    public ProductsController(IProductRepository productRepository) 
    { 
     this.productRepository = productRepository; 
    } 

    // 
    // GET: /Products/ 
    public ActionResult Index(ViewModels.ProductsIndex vm) 
    { 
     return View(vm); 
    } 

} 

視圖模型:

public class ProductsIndex 
{ 
    public List<CTEntities.Product> ProductList { get; set; } 

    public ProductsIndex(IProductRepository prods) 
    { 
     ProductList = prods.List().ToList(); 
    } 

    //Adding this constructor would fix my issue but is there a cleaner way? 
    public ProductsIndex() 
    { 
     var prod = new CTDAL.Product(); 
     ProductList = prod.List().ToList(); 
    } 
} 

回答

2

您的視圖模型應該是一個DTO(數據傳輸對象)......,它應該只包含屬性,它不應該負責獲取數據。你的控制器應得的數據視圖模型,就像這樣:

新視圖模型:

public class ProductsIndex 
{ 
    public List<CTEntities.Product> ProductList { get; set; } 
} 

新控制器:

public class ProductsController : Controller 
{ 
    private readonly IProductRepository productRepository; 

    public ProductsController(IProductRepository productRepository) 
    { 
     this.productRepository = productRepository; 
    } 

    // 
    // GET: /Products/ 
    public ActionResult Index() 
    { 
     var products = productRepository.List().ToList(); 
     return View(products); 
    } 

} 
+0

謝謝 - 哇,我一直使用的ViewModels獲得數據並保持控制器「更薄」......我想現在從單元測試POV中看來是有意義的,不需要測試視圖模型,因爲它沒有做任何事情! 指數()動作在你的例子並不實際使用的視圖模型 - 你的意思是這樣: '變種產品= productRepository.List()ToList(); var vm = new ProductsIndex(); vm.ProductList = products; return View(vm);' – wheelibin

1

一種方法是讓Ninject解決您的ProductsIndex實例。如果你這樣做,它會自動根據需要填寫構造函數參數,只要IProductRepository使用Ninject解決。

你的情況可能是這樣的:

Kernel.Bind<IProductRepository>().To<CTDAL.Product>(); 
Kernel.Bind<ProductsIndex>().ToSelf(); 

現在你ProductsController看起來是這樣的:

public class ProductsController : Controller 
{ 
    private readonly IProductRepository productRepository; 
    private readonly ProductsIndex productsIndex; 
    public ProductsController(IProductRepository productRepository, 
           ProductsIndex productsIndex) 
    { 
     this.productRepository = productRepository; 
     this.productsIndex = productsIndex; 
    } 

    // 
    // GET: /Products/ 
    public ActionResult Index() 
    { 
     return View(productsIndex); 
    } 
} 

請記住,這將不會允許請求的值映射到您的ViewModel,因此Viewmodel中的數據只會依賴於您在解決問題時傳遞給它的參數(在本例中爲產品存儲庫)。