Thomas Ardal

Entrepreneur and founder of elmah.io

Unit-testing HtmlHelper extension methods

I sometimes find myself doing extension methods for the HtmlHelper class in ASP.NET MVC. I like HtmlHelper, but I don’t really dig when the methods generate HTML. This is what partial views are for, right? I usually add small utility methods related to a single view on the view model, but when dealing with shared methods, the HtmlHelper seems like the best choice.

Extension methods in general are pretty easy to unit-test, due to the fact that they are just static methods. However, extension methods on HtmlHelper have all kinds of information available through the “this HtmlHelper” parameter, which can make these methods extremely hard to test. This is the helper method I use to create a new instance of the HtmlHelper class:

public HtmlHelper<T> CreateHtmlHelper<T>(ViewDataDictionary viewData)
{
    var cc = new Mock<ControllerContext>(
        new Mock<HttpContextBase>().Object,
        new RouteData(),
        new Mock<ControllerBase>().Object);
 
    var mockViewContext = new Mock<ViewContext>(
        cc.Object,
        new Mock<IView>().Object,
        viewData,
        new TempDataDictionary(),
        TextWriter.Null);
 
    var mockViewDataContainer = new Mock<IViewDataContainer>();
 
    mockViewDataContainer.Setup(v => v.ViewData).Returns(viewData);
 
    return new HtmlHelper<T>(
        mockViewContext.Object, mockViewDataContainer.Object);
}

The method uses Moq to create mock objects for various ASP.NET MVC classes, but it can easily be ported to Rhino Mocks or other mocking frameworks. Testing extension methods on HtmlHelper is now piece of pie. In the following example, I test an imaginary extension method, named SplitModel, using the CreateHtmlHelper method:

[Test]
public void CanSplitString()
{
    // Arrange
    var htmlHelper =
        CreateHtmlHelper<string>(
            new ViewDataDictionary("Hello World"));
 
    // Act
    string[] result = htmlHelper.SplitModel();
 
    // Assert
    Assert.That(result.Length, Is.EqualTo(2));
}
Show Comments