Thursday, October 1, 2009

Mocking the HtmlHelper class with Rhino.Mocks

In developing HtmlHelper extensions, it's very useful to be able to pass in a mock HtmlHelper. It's not particularly difficult, though I spent a fair amount of time trying to get the Response method, ApplyAppPathModifier to properly return a correct path based on it's value. I finally gave up and decided to simply mock it out by allowing you to supply the path you want it to return via parameters. The current version only works with simple paths of the form /controller/action/id since that's all I needed. Here's the code I'm using to mock out the HtmlHelper for my extensions tests. Add it to your static mocks class.

public static HtmlHelper CreateMockHelper( string routeController,
string routeAction,
object routeID )
RouteData routeData = new RouteData();
routeData.Values["controller"] = routeController;
routeData.Values["action"] = routeAction;
routeData.Values["id"] = routeID;

var httpContext = MockRepository.GenerateStub<HttpContextBase>();
var viewContext = MockRepository.GenerateStub<ViewContext>();
var httpRequest = MockRepository.GenerateStub<HttpRequestBase>();
var httpResponse = MockRepository.GenerateStub<HttpResponseBase>();

httpContext.Stub( c => c.Request ).Return( httpRequest ).Repeat.Any();
httpContext.Stub( c => c.Response ).Return( httpResponse ).Repeat.Any();
httpResponse.Stub( r => r.ApplyAppPathModifier( Arg<string>.Is.Anything ) )
.Return( string.Format( "/{0}/{1}/{2}", routeController, routeAction, routeID ) );

viewContext.HttpContext = httpContext;
viewContext.RequestContext = new RequestContext( httpContext, routeData );
viewContext.RouteData = routeData;
viewContext.ViewData = new ViewDataDictionary();
viewContext.ViewData.Model = null;

var helper = new HtmlHelper( viewContext, new ViewPage() );
if (helper.RouteCollection.Count == 0)
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
return helper;