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(@"Example\helloworld", 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.
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:
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
