How pass different repository object with same interface to my service layer using Ninject?
So I've run into this confusion in the past, and got around it by just not using Ninject. Now that I'm redoing my site I'm at a point where Ninject seems to be handy again, but I've got myself confused. Again.
I have an MVC3 project using a repository pattern. Currently, my Home Controller creates a few objects like OrderRepository.cs, CustomerRepository.cs and sends them to a service called OrderService.cs and CustomerService.cs. I have a Test project that I can use to send in FakeOrderRepository.cs and FakeCustomerRepository.cs. This is handy for unit testing as I go through my project.
However, I realise that by declaring the repositories in my Controller and unit tests, I'm setting up a dependency on those objects. What I would like to do is have no repositories passed, and have my Service layer use Ninject to say "Oh look, IOrderRepository is in my constructor, I better go get OrderRepository".
The issue I ran into last time is that while I can bind OrderRepository to any instance or IOrderRepository in a contructor and bind the two together in my Global.ascx, this seems t开发者_StackOverflowo leave my unit tests high and dry. Unless I go in and switch every bind in my Global.ascx with the object I want passed in (in this case, FakeOrderRepository.cs) every time I run tests, my real repository will be passed in. How can I have my Test project and Controller pass different repositories while using the same IOrderRepository interface?
Whew, long explanation for something that is probably simple. I have a feeling I'm overthinking this and just missing a few key understandings.
tldr: How can I have a constructor in my service layer and pass in a different repository objects from my Controllers and Unit Tests using Ninject.
Continue using ctor injection as much as possible and have everything declare its dependencies and minimise responsibilities
Dont use Ninject in your test context - it should not be necessary - you've made it too complicated if you end up in that place
Assuming you're using Ninject against ASP.NET MVC 3, you should be using the standard integration
It makes sense to use constructor injection in your service classes to inject repositories and you can set that up from global.asax.
To get your unit tests working you have a couple of options:
Setup the bindings to the fake repositories in your tests. In other words create a different NInject module/kernel in your test setup method. If these are just controller tests then the bindings in global.asax won't apply so you would have to set up alternative bindings anyway or setup the dependencies manually (which is the second option).
Use constructor injection to inject your service classes into the controller and have NInject handle this at runtime by overriding the controller factory. Then in your unit tests you could create your service classes, and fake repositories manually and pass the service objects into the controllers via their constructors.
I found this article helpful to understand how to integrate NInject into an MVC project: http://msdn.microsoft.com/en-us/magazine/dd942838.aspx
精彩评论