user82334
user82334

Reputation: 279

How to unit test asp.net mvc base controllers without hitting the database?

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);
    }
}

Upvotes: 0

Views: 1374

Answers (3)

Hldev Zkran
Hldev Zkran

Reputation: 21

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.

Upvotes: 0

eglasius
eglasius

Reputation: 36037

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 :).

Upvotes: 1

Oscar Cabrero
Oscar Cabrero

Reputation: 4169

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

Upvotes: 0

Related Questions