Thursday 1 July 2010

Testing HtmlHelpers in ASP.NET MVC 2

It’s been a while since I’ve blogged, no excuses really except I haven’t had anything I wanted to share.  I found this fairly interesting though.

I’m currently creating an ASP.NET MVC 2 site and I wanted to write some tests for my custom HTMLHelpers.  These are largely testable by doing some simple mocking.  The Helper that you pass in holds lots of information about the HttpContext, something that was very difficult to work with for unit testing prior to ASP.NET MVC 2 but is now quite easy.

The following code will create a testing controller called base controller to pretend to be the controller in context, mock the context and the view data information along with the view itself to allow you to test.  All you need to do is setup results for the methods you need in your test.  I’ve used RhinoMocks and nUnit, but the code is similar to other techs.

// Member variables for everything so my tests can setup some local test data
private ControllerContext _controllerContext;
private ViewContext _viewContext;
private ViewDataDictionary _viewData;
private IViewDataContainer _viewDataContainer;
private HtmlHelper _target;
 
[SetUp]
public void SetUp()
{
    _viewData = new ViewDataDictionary();
 
    // A memory stream for the view context to pretend to write to
    MemoryStream memoryStream = new MemoryStream();
    TextWriter tw = new StreamWriter(memoryStream);
 
    // Create a contextual controller
    ControllerBase controller = new BaseController();
    _controllerContext = new ControllerContext(MockRepository.GenerateStub<HttpContextBase>(), new RouteData(), controller);
    controller.ControllerContext = _controllerContext;
 
    // The container for the view data
    _viewDataContainer = MockRepository.GenerateStub<IViewDataContainer>();
    _viewDataContainer.ViewData = _viewData;
 
    // The view context, you can pull out the temp data dictionary if you need to test with it.
    ViewContext context = new ViewContext(_controllerContext, MockRepository.GenerateStub<IView>(), _viewData,
                                          new TempDataDictionary(), tw);
 
    // Constructor for the helper.
    _target = new HtmlHelper(context, _viewDataContainer);
}

I’ve used members to allow my tests to create view data info, or change something about the containers if they need to.  Using the above you should be able to mock or create everything your HTML helpers have access to, just include the namespace of your helper in the usings and you’ll eb able to access your method by _target.YourHelper();