views:

57

answers:

2

I have implemented my mvc base controller called DefaultController using dependency injection pattern in order to be able to construct 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, homecontroller, usercontroller, etc.

Now, building some test cases I found myself in a situation where I don't 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?

+2  A: 

Your HomeController needs to have a matching "injectable" constructor, which would then call the base constructor.

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

    }

Now, in your test, you would create your HomeController using that constructor, and pass in a mocked up session and user repository. Speaking of mocking, you might also be interested in Scott Hanselman's MvcMockHelpers classes, with code for many popular mocking frameworks.

womp
+2  A: 

I don't see why you have two constructors. You should only have one, get rid of the constructor with no parameters. Using a DI framework like Castle Windsor, or my preferred one, Autofac will handle all of this for you. Then as far as testing is concerned use something like Moq. Ie

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

Register DefaultController, ISessionHelper and IUserRepository with your DI framework. Something along the lines of:

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

That way, you can pull DefaultController from the container and the DI framework will inject the two parameters for you. I wrap up a static method to access my DI container, it looks like:

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

Basically head over to Autofac and have a look. There's 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 ewww repositories. With .Net and generics etc... just create yourself an 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);

Means you only need to pass in one thing and you can use it for whatever. Rather than having to pass in sometimes many repositories. Also sets you up nicely for the Unit Of Work pattern.

Bealer
Just to note - if you get rid of the parameterless constructors, then you also need to roll your own Controller factories.
womp
Why factories? In the case above the DI framework is injecting everything for you. Things like ISessionHelper and IUserRepository should run off a static Session, and most likely won't have any values that you want to pass in.All you have to do is call:var controller = IoC.Resolve<DefaultController>(); and it's all built for you.Injecting via the constructor means you have to pass variables in via method params, or set public properties (much like the Command pattern).
Bealer