We started out a new project a few weeks back and aimed high for testing this time around. We were in luck for this project, all new code and just a few connection points to other systems. Although, the project has the potential to impact on many system we are hard focused on solving the one issue that brings the highest business value.So the testing was going great but some things nagged me, especially when it came to the web project. It's a simple interface and I really fished out all the information from the code behind and was able to push most of it back to the presenter logic, leaving only the thinnest possible layer.But still, there were a few calls to store data in the HttpSession and accessing HttpResponse. (I really wished they interfaced those types and no, IHttpSession is NOT the interface for HttpSession, sorry). I started experimenting with creating an interface and wrapping the few methods I needed in my own type when I stumbled on a framework that did that for me. I didn't realize that I was duck typing, but once I did, this was the solution. I started out to test a duck typing framework by David Mayer and it really does wonder for my tests.So, for HttpResponse I create the IHttpResponse interface with just one method, Redirect(). Like this (well, there are two methods to handle the overload):
public interface IHttpResponse
{
void Redirect(string url);
void Redirect(string url, bool endResponse);
}
Then, in the code behind I just make my call as slim as possible, no evil, hard-to-test code in the code behind, thank you!
protected void ButtonSearchClick(object sender, EventArgs eventArgs)
{
_SearchPresenter.GotoSearchResult(DuckTyping.Cast<ihttpresponse>(Response), tbSearchText.Text);
}
This makes it possible to use Rhino Mocks for HttpResponse. Instead of the live HttpResponse you can inject your mock and test away
[Test]
public void GotoSearchResult()
{
IHttpResponse response = _Mocks.CreateMock<ihttpresponse>();
using (_Mocks.Record())
{
response.Redirect("Result.aspx?query=QueryString001");
// More mock expectations
}
using (_Mocks.Playback())
{
_SearchPresenter.GotoSearchResult(response, "QueryString001");
// And some asserts
}
}
So this makes things more robust and its way easier to mock things. This really enables me to slim down the code behind even further. Sweet!