I have been creating an application using the new ASP.NET MVC Framework in the ASP.NET 3.5 Extensions Preview over the past week and am fumbling with the view-controller testing. I stopped testing the view-controller interaction altogether, because it feels incredibly time consuming and laborious over what I have experienced in the past with Model-View-Presenter.
My Experience with Model-View-Presenter
In a fairly recent post, I talked about how I have finally gotten into a groove with View-Presenter Test-Driven Development:
MVP in ASP.NET - Development with Just the Promise of a View
It was an uphill climb, but I feel very, very comfortable with testing the Model-View-Presenter Pattern in ASP.NET. Most of the success has come from doing several projects with the Web Client Software Factory which helps with the View-Presenter Implementation, which you can also learn about in the recently released MVP Bundle.
The beauty about the Model-View-Presenter Pattern is that the Presenter Constructor typically accepts a View Interface, which can easily be mocked by a mocking Tool. In the example I mention in the previous post, View-Presenter Testing is as simple as:
[Test]
public void EmptyCustomerNameShouldCauseInvalidCustomerMessage()
{
MockRepository mocks = new MockRepository();
IAddCustomerView mockView = mocks.CreateMock<IAddCustomerView>();
AddCustomerPresenter presenter = new AddCustomerPresenter(mockView);
Expect.Call(mockView.CustomerName).Return(string.Empty);
Expect.Call(mockView.CustomerTitle).Return("Jester");
Expect.Call(mockView.PhoneNumber).Return("555-1212");
mockView.Message = "Invalid Customer...";
mocks.ReplayAll();
presenter.onAddCustomer();
mocks.VerifyAll();
}
The key here is that all I need to do is mock the View Interface, in this case IAddCustomerView. I can then setup expectations on the view and test to make sure those are met. This is incredibly easy after awhile and has become somewhat second nature to me.
ASP.NET MVC Framework - View-Controller Testing
Fast forward to this week where I have been all smiles with the simplicity of the ASP.NET MVC Framework and very impressed with its extensibility. Particularly satisfying to me has been how happy I have been with using dependency injection with it using Castle Windsor, Spring.NET, etc. The IControllerFactory in the ASP.NET MVC Framework is really, really nice. I mentioned it here with Castle Windsor and SpringFramework.NET:
SetDefaultControllerFactory and IControllerFactory in ASP.NET MVC Framework
This is cool, because Dependency Injection in webforms has always felt a little kludgy and now it finally feels good in the ASP.NET MVC Framework.
However, the testability of the View-Controller Interaction seems like a lot of effort. Several people have been pointing to Haack's post:
Writing Unit Tests For Controller Actions
but the mocking framework versions of his tests are a lot more effort than what you would have to do with MVP. Here is a test to verify a simple redirect:
[Test]
public void VerifyAboutRedirectsToCorrectActionUsingMockViewFactory()
{
RouteTable.Routes.Add(new Route
{
Url = "[controller]/[action]",
RouteHandler = typeof(MvcRouteHandler)
});
HomeController controller = new HomeController();
MockRepository mocks = new MockRepository();
IHttpContext httpContextMock = mocks.DynamicMock<IHttpContext>();
IHttpRequest requestMock = mocks.DynamicMock<IHttpRequest>();
IHttpResponse responseMock = mocks.DynamicMock<IHttpResponse>();
SetupResult.For(httpContextMock.Request).Return(requestMock);
SetupResult.For(httpContextMock.Response).Return(responseMock);
SetupResult.For(requestMock.ApplicationPath).Return("/");
responseMock.Redirect("/Home/Index");
RouteData routeData = new RouteData();
routeData.Values.Add("Action", "About");
routeData.Values.Add("Controller", "Home");
ControllerContext contextMock = new
ControllerContext(httpContextMock, routeData, controller);
mocks.ReplayAll();
controller.ControllerContext = contextMock;
controller.About();
mocks.VerifyAll();
}
We end up mocking a lot more than just a View Interface and setting up a lot of extra classes like ControllerContext and RouteData. To be fair, the ASP.NET MVC Framework is still in CTP and we do have much more ability to mock with all the wonderful interfaces, but this just seems like way too much typing over what I am used to with Model-View-Presenter. Haack also shows a Specific SubClass Pattern which does greatly reduce the code, but I still just find the Model-View-Presenter Testing so much easier.
Conclusion
My gut here is that unless the View-Controller Testing is made simpler, I am less apt to do it. I miss the simple mocking of the View Interface that I get from Model-View-Presenter and find that although I have a much richer environment for testing, it seems like a lot more work.
If anyone can share some insight, I would greatly appreciate it. I am at a loss for what I am experiencing.
Posted
Sun, Dec 16 2007 6:27 PM
by
David Hayden