views:

1538

answers:

4

Is there any way to (unit) test my own HtmlHelpers? In case when I'd like to have custom control (rendered by HtmlHelper) and I know requierements for that control how could I write tests first - and then write code? Is there a specific (nice) way to do that?

Is it worth?

A: 

You can test your HtmlHelpers, because they are just static methods that return a string in most cases.

Example:

Assert.IsEqual(MakeParagraph("hello"), "<p>hello</p>");

Personally, I don't think it's really necessary (or worth it) though.

Timothy Khouri
A: 

You mention testing a custom control rendered by HtmlHelper, which I presume is rendering a User Control. I haven't managed to find a way to test these, I can't get around exceptions all over the old-school ASP.NET stack.

My question about this was: How can I unit test an MVC UserViewControl

No answers yet!

Simon Steele
+1  A: 

In response to Timothy; it may not be worth testing the packaged HtmlHelper Extensions but what about when you are creating custom HtmlHelper Extensions e.g.

public static String ComboWithLabel(this HtmlHelper htmlHelper,String name, String value) { return "" + htmlHelper.TextBox(name,value) + ""; }

The example above will render the correct output and makes use of the existing HtmlHelper extension Textbox() but it is not possible to call the ComboWithLabel method in testing without passing in a valid (not null) HtmlHelper. It then becomes necessary to creat e Mock HtmlHelper in your tests so that you can pass that in.

+9  A: 

The main problem is that you have to mock the HtmlHelper because you may be using methods of the helper to get routes or values or returning the result of another extension method. The HtmlHelper class has quite a lot of properties and some of them quite complex like the ViewContext or the current Controller.

This post from Ben Hart that explains how to create such a mock with Moq. Can be easily translated to another mock framework.

This is my Rhino Mocks version adapted to the changes in the MVC Framework. It's not fully tested but it's working for me but don't expect perfect results:

    public static HtmlHelper CreateHtmlHelper(ViewDataDictionary viewData)
    {
        var mocks = new MockRepository();

        var cc = mocks.DynamicMock<ControllerContext>(
            mocks.DynamicMock<HttpContextBase>(),
            new RouteData(),
            mocks.DynamicMock<ControllerBase>());

        var mockViewContext = mocks.DynamicMock<ViewContext>(
            cc,
            mocks.DynamicMock<IView>(),
            viewData,
            new TempDataDictionary());

        var mockViewDataContainer = mocks.DynamicMock<IViewDataContainer>();

        mockViewDataContainer.Expect(v => v.ViewData).Return(viewData);

        return new HtmlHelper(mockViewContext, mockViewDataContainer);
    }
Marc Climent
sadly the blog post errors but the above explains quite well what you need to do
MJJames