ASP.NET MVC Ninject / DI - 没有为此对象定义无参数构造函数
我正在尝试使用 DI/Mocks (Ninject/Moq) 进行单元测试,将产品存储库注入到我的控制器中,然后将其传递到我的视图模型以允许对其进行测试。
它工作得很好,允许我对控制器操作和视图模型进行单元测试。但是,当我运行应用程序时,我得到“没有为此对象定义无参数构造函数”......现在我知道这是由于控制器尝试初始化没有无参数构造函数的视图模型。
我可以创建构造函数并从中调用我的具体存储库(因此单元测试仍然使用注入/模拟的)。
这是正确的方法吗?任何建议将不胜感激!
控制器:
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();
}
}
I am using trying to get my head round unit testing with DI/Mocks (Ninject/Moq) to inject a Product repository into my controller which I then pass to my view model in order to allow testing of that.
It is working great and is allowing me to unit test the controller action and the view model. However, when I run the application I get "No parameterless constructor defined for this object"....now I know this is due to the controller trying to initialise the View Model which doesn't have a parameterless constructor.
I could create the constructor and call my concrete repository from that (so unit tests still use the injected/mocked one).
Is this the correct approach? Any advice would be greatly appreciated!
Controller:
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);
}
}
View model:
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的视图模型应该是一个 DTO(数据传输对象)...因为它应该只包含属性,并且不应该负责获取数据。您的控制器应该获取视图模型的数据,如下所示:
新视图模型:
新控制器:
Your View Model should be a DTO (Data Transfer Object) ... in that it should only contain properties, and it should NOT be responsible for getting data. Your controller should get the data for the View Model, like so:
New View Model:
New Controller:
一种方法是让 Ninject 解析您的
ProductsIndex
实例。如果您这样做,它会根据需要自动填充构造函数参数,前提是IProductRepository
也使用 Ninject 解析。在您的情况下可能是这样的:
现在您的
ProductsController
可能如下所示:请记住,这不允许将请求值映射到您的 Viewmodel,因此 Viewmodel 中的数据只会是取决于您在解析它时传递给它的参数(在本例中为产品存储库)。
One approach would be to let Ninject resolve your
ProductsIndex
instances. If you do that, it will automatically fill in the constructor arguments as required, providedIProductRepository
is resolved using Ninject as well.In your case could be something like:
Now your
ProductsController
could look like this:Keep in mind that this would not allow for request values to be mapped to your Viewmodel, so the data in your Viewmodel would only be dependent on the parameters you pass into it at the time you resolve it (in this case the product repository).