Testing MonoRail Controllers

At first glance of the MonoRail documentation, it seems as if testing MonoRail controllers will be an easy and enjoyable task.Using the Castle.MonoRail.TestSupport, as described in the MonoRail documentation, works well for the first several test fixtures. After implementing a large number of test fixtures, you will notice two things.

  1. Controller tests are running slowly. This is a side effect of each test fixture having to start ASP.NET.
  2. Controller tests are failing randomly.

Each controller test fixture added makes the problem worse. It got so bad that we were unable to get all of our tests to pass consistently. We had to fix the problem.Our Two Part Solution:

  1. Move all of the controller tests into one test fixture. After doing this, all controllers tests passed consistently. This was a great short term solution. Our tests were passing, but they were still slow. We had to find a way to make things run faster. This led us to #2.
  2. Code the controllers in our system using Model-View-Presenter (MVP). This allowed us to test our controllers without requiring our test fixtures to extend Castle.MonoRail.TestSupport.

Using MVP required surprising little code modification. To convert an existing controller to our new MVP style required only adding View to the front of every property/method call within the actions that were being converted RenderView("junk") became View.RenderView("junk").Below is a more detailed example of how we now implement and test our controllers.Example:

[Test]public void NeighborhoodCriteriaIsCalculatedCorrectlyForASubRegion(){    TestView view = new TestView();    NeighborhoodsController controller = new NeighborhoodsController();    controller.View = view;    string subRegion = "SanFrancisco";    controller.ListBySubRegion(subRegion);    Assert.AreEqual("subRegion=SanFrancisco", view.PropertyBag["neighborhoodCriteria"]);}public class NeighborhoodsController : ApplicationController{    public void ListBySubRegion(string subregion)    {        View.PropertyBag["neighborhoodCriteria"] = "subRegion=" + subregion;    }}public class ApplicationController : SmartDispatcherController, IView, IPresenter{    private IView view;    public ApplicationController()    {        View = this;    }    public IView View    {        get { return view; }        set { view = value; }    }}public interface IView : IComponentView{    void CancelLayout();    void RenderEmailAndSend(string emailTemplate);}public interface IComponentView{    IDictionary PropertyBag { get; }    void RenderText(string text);    void RenderView(string view);    void RenderView(string controller, string view);    void RenderView(string view, bool cancelLayout);}

6 Responses

  1. Hey Adam, take a look to the Eleutian’s guys approach, to TDD. It’s very interesting.

  2. I have seen that post we we first started this project. We had much simpler needs, so we did not need to mock out everything. If we ever need more, I will be sure to look at it again.

  3. Just FYI, hammett recently posted an article with a new BaseControllerTest implementation on the castle trunk. You can read more at the link: http://using.castleproject.org/display/MR/TDDingControllers

    Hope that helps!

  4. […] my Testing MonoRail Controllers post for more […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: