Monorail #3 : Unit Testing and ViewComponents

UNIT TESTING

After the past 2 1/2 posts I’ve migrated my unit tests to use the BaseControllerTest abstract class that originated from the Eleutian guys, but is now a part of the Castle MonoRail trunk download.
Here is my ExampleControllerTests class:

   1: using Castle.MonoRail.TestSupport;
   2: using JasonMeridth.Controllers;
   3: using NUnit.Framework;
   4:  
   5: namespace JasonMeridth.Tests.Controllers
   6: {
   7:     [TestFixture]
   8:     public class ExampleControllerTests : BaseControllerTest
   9:     {
  10:         private ExampleController exampleController;
  11:  
  12:         [SetUp]
  13:         public void Setup_context()
  14:         {
  15:             exampleController = new ExampleController();
  16:             PrepareController(exampleController, "", "Example", "helloworld");
  17:         }
  18:  
  19:         [Test]
  20:         public void Controller_should_not_be_null()
  21:         {
  22:             Assert.IsNotNull(exampleController);
  23:             Assert.AreEqual(@"Examplehelloworld", exampleController.SelectedViewName);
  24:         }
  25:  
  26:         [Test]
  27:         public void Should_see_hello_world_message()
  28:         {
  29:             exampleController.HelloWorld();
  30:  
  31:             Assert.IsNotNull(exampleController.PropertyBag["message"]);
  32:  
  33:             string message = exampleController.PropertyBag["message"].ToString();
  34:  
  35:             Assert.AreEqual("Hello World", message);
  36:         }
  37:     }
  38: }
 
An excellent post by Sean Chambers shows how to test controllers also.  As Sean states the PrepareController method is the core method we need for our test wire-up.  You pass this method the controller, the area, and the action and it sets up the IRailsEngineContext by creating instances of mock classes that will respond to your test.  Looking at the trunk source code is always beneficial, so I highly suggest it.
 
Remember, learning a new framework shouldn’t cause you to forget your Test-Driven Development Mantra:  Red, Green, Refactor.  Don’t get me wrong, I’m still researching what options are available to me from the BaseControllerTest abstract class, but with the help of JoeyDotNet’s posts and reading sites like http://using.castleproject.org and http://api.castleproject.org and, of course, reading the source code, makes it a lot easier.

VIEW COMPONENTS

As many of the developers who use MonoRail regularly have stated in many blogs, ViewComponents are like re-usable controls.  I had a situation where I wanted today’s date to show up on my menu on every page.  A ViewComponent came to mind.

To create a view component you have to add the following folders to your project:

image

Project
—ViewComponents Folder
——–Component.cs (in my case, MenuComponent.cs)
—View Folder
——–components folder
————-<component name> folder (in my case, menucomponent)
———————-default.vm

The default.vm is the expected output of your view component.  Just like the action views, this is what will be displayed when your component is used.

The code for the MenuComponent.cs is: (VERY simple)

   1: using System;
   2: using Castle.MonoRail.Framework;
   3:  
   4: namespace JasonMeridth.ViewComponents
   5: {
   6:     public class MenuComponent : ViewComponent
   7:     {
   8:         public override void Render()
   9:         {
  10:             PropertyBag["today"] = DateTime.Now;
  11:             base.Render();
  12:         }
  13:     }
  14: }

All I want is today’s date.  The rest is in the NVelocity file:

   1: <div id="menu">
   2:     <ul>
   3:         <li class="first"><a href="../../home/index.rails">Home</a></li>
   4:         <li><a href="http://www.lostechies.com/blogs/jason_meridth" target="_blank">My Blog</a></li>
   5:         <li><a href="../../contact/contactform.rails">Contact</a></li>
   6:     </ul>
   7:  
   8:     <div id="date">$today.ToLongDateString()</div>
   9: </div>

Notice the $today.ToLongDateString() section.  $today is coming from Today’s date which was placed in the PropertyBag by the controller.

Easy.  And now to inject the view component into my default.vm for layouts:

   1: <div id="header">
   2:             <img src="../Content/images/lucas_header.JPG" />
   3:             <h1><span>JasonMeridth</span>.com<sup>1.0</sup></h1>
   4:         </div>
   5:     
   6:         #component(MenuComponent)    
   7:  
   8:         <div id="primarycontent">
   9:         
  10:             
  11:             <!-- primary content start -->
  12:             $childContent
  13:             <!-- primary content end -->
  14:     
  15:         </div>

Please refer back to my first post for the whole file and you’ll notice the code that was removed and placed into the view component’s default.vm and the new line of code, #component(MenuComponent) in the default layout default.vm.  It’s that simple.

I hope this helps.  This was ViewComponents 101.  I will delve deeper into some tips and tricks with these later in these posts. 

***Joey does have a post about separating the ViewComponents into a new assembly, therefore allowing you distribute your components and make them re-usable.

Some excellent helper posts from other developers:
1. JoeyDotNet: Post 1, Post 2, Post 3 (I swear this isn’t programmer worship, he’s just my best resource right now, plus he’s put out 2 production MonoRail sites – a good resource)
2. Sean Chambers: Post 1

NEXT POST: Validation

Prior Posts:
Monorail #0:Controllers
Monorail #1:Reasons, Setup, and First Output
Monorail #2:Layouts and Rescues

kick it on DotNetKicks.com

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jason Meridth

Continuously learning software developer trying to not let best be the enemy of better
This entry was posted in castle, monorail. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

Comments are closed.