How to solve basic controller dependency injection for testing purposes?

I implemented my base mvc controller called DefaultController using a dependency injection pattern to be able to create test cases. Example below:

public class DefaultController : Controller { protected readonly ISessionHelper _sessionHelper; string _thisUserOpenID; protected IUsersRepository _UserRepository; ... public DefaultController() { } //not for testing public DefaultController(ISessionHelper session, IUserRepository repo) { _sessionHelper=session; _UserRepository = repo; } } 

Then I have my controllers using this controller, homcontroller, usercontroller, etc.

Now, having created some test cases, I found myself in a situation where I do not know how to actually use the injection dependency pattern.

  [TestMethod] public void Welcome_Message_In_ViewData_Has_Coockie_User_Display_Name() { // Below I want to insert FakeRepositories using //ISessionHelper and so on. but the constructor //for homecontroller don't have it. HomeController controller = new HomeController(); 

Any ideas?

+6
c # asp.net-mvc
source share
2 answers

Your HomeController must have an appropriate "injectable" constructor, which then calls the base constructor.

 public HomeController(ISessionHelper session, IUserRepository repo) : base(session, repo) { } 

Now, in your test, you should create your HomeController using this constructor and pass it to the split session and user repository. Speaking of mockery, you might also be interested in the Scott Hanselman MvcMockHelpers class , with code for many popular funny frameworks.

+5
source share

I do not understand why you have two constructors. You should have only one, get rid of the constructor without parameters. Using a DI infrastructure such as Castle Windsor, or my preferred one, Autofac will handle it all for you. Then, regarding testing, use something like Moq. Those.

 public DefaultController(ISessionHelper session, IUserRepository repo) { _sessionHelper = session; _UserRepository = repo; } 

Register DefaultController, ISessionHelper and IUserRepository with your DI card. Something like:

 Register(new DefaultController()); (it is something like that in Autofac) Register<SessionHelper>().As<ISessionHelper>(); Register<UserRepository>().As<IUserRepository>(); 

This way you can pull the DefaultController out of the container, and the DI structure will introduce two parameters for you. I am completing the static method of accessing the DI container, it looks like this:

 var controller = IoC.Resolve<DefaultController>(); 

Basically go to Autofac and see. There is also a web module for registering your controllers for you.

Then for testing just use Moq or find some form of "AutoMocker" (google it). I would do:

 var session = new Mock<ISessionHelper>(); var repo = new Mock<IUserRepository>(); repo.Setup(s => s.FindById(123)).Returns(new User()); var conroller = new DefaultController(session.Object, repo.Object); controller.Execute(); 

Also repositories ewww. With .Net and generics, etc ... just create yourself a nice ISession.

 var session = IoC.Resolve<ISession>(); var user1 = session.Get<User>(123); var user2 = session.Get<User>(u => u.Username == "admin"); session.Update(user3); 

So you only need to convey one thing, and you can use it for anything. Instead of skipping many repositories sometimes. Also great for Unit Of Work template.

+3
source share

All Articles