views:

351

answers:

3

I have been using unit testing for controllers with the 'poor man's' dependency injection technique. Each controller inherits from a base controller to query data for the master page. How do I unit test the controller with it inheriting from base controller without hitting the database?

public class HomeController : BaseController
{
    IUserRepository _userRepository;

    public HomeController() : this(new UserRepository()) {

    }

    public HomeController(IUserRepository userRepository) {
        _userRepository = userRepository;
    }
}

public class BaseController : Controller
{
    protected override void Execute(System.Web.Routing.RequestContext requestContext)
    {
        MyDataContext db = new MyDataContext();

        ViewData["masterPageData"] = db.GetSomeData();

        base.Execute(requestContext);
    }
}
A: 

maybe by having a interface on your datacontext and have your datacontext injected then implement a mock of the interface that returns you the data without hitting the database

Oscar Cabrero
A: 

Code would look something like this:

public class HomeController : BaseController
{
    IUserRepository _userRepository;
    public HomeController() : this(new UserRepository()) { }
    public HomeController(IUserRepository userRepository) : base() {
        _userRepository = userRepository;
    }
    public HomeController(IUserRepository userRepository, ISomeRepository someRepository) : base(someRepository) {
        _userRepository = userRepository;
    }
}
public class BaseController : Controller
{
    ISomeRepository _someRepository;
    public BaseController(ISomeRepository someRepository)
    {
        _someRepository = someRepository;
    }
    public BaseController()
    {
        _someRepository = new SomeRepository();
    }
    protected override void Execute(System.Web.Routing.RequestContext requestContext)
    {
        MyDataContext db = new MyDataContext();
        ViewData["masterPageData"] = _someRepository.GetSomeData();
        base.Execute(requestContext);
    }
}

That said, if you use a DI framework, you would only need 1 constructor in each class. So you can see how it starts leaning towards using one :).

eglasius
A: 

I would say the problem is that your base controller uses different data access approach. What's more, BaseController is hard wired to DataContext and that results in testability problems.

If BaseController needs to get data from database, why not to use repository in it as well? If full-fledged IoC container is not available, you can inject repository dependency in inherited controllers and pass it to the BaseController.

This way it's easy to create a mock for master page data.

Hldev Zkran