I was having a hard time easily testing controller classes with the MVC Framework December CTP. Now it’s easier. For some background, I’m writing ASP.NET MVC in Action for Manning, so I’m going through all kinds of scenarios, and in the first chapter with the tiny little Hello World samples, it’s now easier to test these. Consider the following controller:
using System.Web.Mvc;
namespace MvcApplication.Controllers
{
public class HelloWorld1Controller : IController
{
public void Execute(ControllerContext controllerContext)
{
controllerContext.HttpContext.Response.Write(
"<h1>Hello World1</h1>");
}
}
}
And here’s my unit test:
using MvcApplication.Controllers;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
namespace MvcApplicationTest.Controllers
{
[TestFixture]
public class HelloWorld1ControllerTester
{
[Test]
public void ShouldRender()
{
var response = new ResponseWriteStub();
var contextStub = new HttpContextStub(response);
var controller = new HelloWorld1Controller();
controller.Execute(new ControllerContextStub(controller, contextStub));
Assert.That(response.ActualWritten, Is.EqualTo("<h1>Hello World1</h1>"));
}
}
}
Pretty darned simple. Below are my stub classes.
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcApplicationTest
{
public class ControllerContextStub : ControllerContext
{
public ControllerContextStub(IController controller)
: base(new RequestContext(new HttpContextStub(), new RouteData()), controller)
{
}
public ControllerContextStub(IController controller, HttpContextBase contextBase)
: base(new RequestContext(contextBase, new RouteData()), controller)
{
}
}
}
using System.Web;
namespace MvcApplicationTest
{
public class HttpContextStub : HttpContextBase
{
private readonly HttpResponseBase _response;
public HttpContextStub(HttpResponseBase response)
{
_response = response;
}
public HttpContextStub()
{
}
public override HttpResponseBase Response
{
get { return _response; }
}
}
}
using System.Web;
namespace MvcApplicationTest.Controllers
{
public class ResponseWriteStub : HttpResponseBase
{
public string ActualWritten;
public override void Write(string s)
{
ActualWritten = s;
}
}
}
@ jonnii,
I chose not to use a mocking library for this blog post because it would clutter the sample.
@Ayende,
Just give me a chance. In my book, I’m going through all kinds of scenarios, and this is one of the most basic. Previously, I didn’t even write a unit test for this because it was such a pain.
Why are you not using a mocking framework?
Jeffrey,
Huh?
This is not testing a controller. This is testing IHttpHandler. The interface is just the same, and the implications of that are likewise. No one is likely to work at this level.
What is important is showing testability for the real scenario, inheriting from Controller