Tell don't ask

November 10, 2009

BDD with MSpec and Rhino Auto Mocks (part 1)

Filed under: C# — telldontask @ 11:40 pm
Tags: , , ,

I’ve long been a fan of test driven development in theory but in practice have experienced many of the issues which turn people off TDD and unit testing in general.

Brittle tests which do too much, tell you very little about the meaning behind the code and are more a hindrance than a help when it comes to making changes at a later date.

Well as you may have guessed, given the title of this post, I have found an answer to these problems in the form of BDD using MSpec and Rhino Automocking. I have been using this approach for a good while now and continue to be pleasantly surprised by just how much fun it is writing my tests, but also how stupidly easy they are to change, and how well they document my project’s requirements.

Update: You can get MSpec from github.

External Tool

It’s a good idea to set up an external tool in Visual Studio to run your MSpec tests and produce html output.

Create a new external tool which launches mspec.exe with the following arguments.

$(TargetName)$(TargetExt) --html "$(ProjectDir)\Report.html"

Make sure the initial directory is $(BinDir) and tick Use output window.

image 

Using your favourite Test Runner

Included in the MSpec download are scripts to configure various test runners to recognise and run MSpec tests.

image

Simply run the bat file which relates to your build runner and way you go!

Writing Specifications

Ensure you add a reference (in your Tests Project) to Machine.Specifications.dll.

Now the fun begins.

I’ve created an ASP.NET MVC site and empty class library Tests project.

Let’s say we want to create a simple page which allows users to search for a product.

We’ll start by creating a new folder in our tests folder called Controllers and add a new class file called ProductControllerTets.cs

Having discussed this feature in detail with the client, I’ve a pretty good idea of what they want, so I start with the following.

  1. using Machine.Specifications;
  2.  
  3. namespace MSpecExample.Tests.Controllers
  4. {
  5.     [Subject("Product Search")]
  6.     public class when_product_search_page_requested
  7.     {
  8.         It should_return_product_search_page;
  9.     }
  10.  
  11.     [Subject("Product Search")]
  12.     public class when_asked_for_products_matching_search_term
  13.     {
  14.         It should_retrieve_a_list_of_products_with_titles_containing_the_search_term;
  15.         It should_return_the_list_of_products_to_the_user;
  16.     }
  17.  
  18.     [Subject("Product Search")]
  19.     public class when_empty_search_term_entered
  20.     {
  21.         It should_return_an_error_message;
  22.     }
  23. }

What I particularly like about this, is that you can really think about exactly what you’re doing and express it in code which will eventually become executable tests without actually implementing any code (yet!).

If we now build our test project and run the tests using the console runner via the external tool we set up earlier), we’ll get a report.html file in the tests project which looks like this…

image

In part 2, we’ll start implementing these tests.

In part 3, we’ll introduce Rhino AutoMocker.

April 24, 2009

ASP.NET and JQuery MVC Menu Part 1

Filed under: C#,MVC — telldontask @ 8:40 am
Tags: , ,
Other posts in this series:

One of the key differences between ASP.NET Web forms and ASP.NET MVC is that WebForms contained many controls which you could use on your web pages and MVC doesn’t.

Not that this is a bad thing, the difficult thing about WebForms was the horrendous html they generated and the hoops you had to go through to gain fine control over them.

In this series of posts I will describe how to create a fully functional Menu using Html, JQuery and some C# Helper Methods.

Part 1 – Creating an MVC Menu

Creating a menu in MVC is actually pretty straightforward once you realise you’re going to have to do some of the dirty work yourself.

Start with a standard Unordered List.

  1. <ul id="main-menu">
  2.     <li>
  3.         <a href="/">Home</a>
  4.     </li>
  5.     <li>
  6.         <a href="/ContactUs">Contact Us</a>
  7.         <ul>
  8.             <li>
  9.                 <a href="/FindUs">How to find us</a>
  10.             </li>
  11.         </ul>
  12.     </li>
  13. </ul>

Note that we have another unordered list inside the main list to create a hierarchical menu.

Now I know what you’re thinking, that’s not MVC that’s just HTML. So let’s make life easier for ourselves and introduce a helper method to render these list items for us.

  1. public static string ListItem(this HtmlHelper helper, string linkText, string actionName, string controllerName)
  2. {
  3.     TagBuilder builder = getListItem(helper, linkText, actionName, controllerName);
  4.     return builder.ToString();        
  5. }

Nothing fancy here, but note that we’re passing in the action and controller names. The actual work is done in the getListItem method.

  1. static TagBuilder GetListItem(HtmlHelper helper, string linkText, string actionName, string controllerName)
  2. {
  3.     var linkHtml = HtmlHelper.GenerateLink(helper.ViewContext.RequestContext, helper.RouteCollection, linkText, null, actionName, controllerName, null, null);
  4.  
  5.     var builder = new TagBuilder("li");
  6.  
  7.     var isCurrent = IsCurrentAction(helper, actionName, controllerName);
  8.  
  9.     if (isCurrent)
  10.     {
  11.         builder.MergeAttribute("class", "current");
  12.     }
  13.  
  14.     builder.InnerHtml = linkHtml;
  15.     return builder;
  16. }

This is where the fun starts (honestly!).

  1. First off we generate a link for the specified action and controller. This will work with whatever routing you have set up and generate a link to the action.
  2. We create a new TagBuilder to render our list item
  3. We’ll look at the IsCurrentAction method next, it checks if the specified action/controller is the one currently being presented to the user
  4. If this is the current Action then set the list item’s class to “current”
  5. Put the link inside the li tag

IsCurrentAction is pretty straightforward too…

  1. static bool IsCurrentAction(HtmlHelper helper, string actionName, string controllerName)
  2.         {
  3.             string currentControllerName = (string) helper.ViewContext.RouteData.Values["controller"];
  4.             string currentActionName = (string) helper.ViewContext.RouteData.Values["action"];
  5.  
  6.             if (currentControllerName.Equals(controllerName, StringComparison.CurrentCultureIgnoreCase) &&
  7.                 currentActionName.Equals(actionName, StringComparison.CurrentCultureIgnoreCase))
  8.             {
  9.                 return true;
  10.             }
  11.  
  12.             return false;
  13.         }

So how would you use your new helper methods?

  1. <ul id="main-menu" class="menu collapsible">
  2.     <%= Html.ListItem("Home", "Index", "Home") %>
  3.     <%= Html.ListItem("Contact Us", "Index", "ContactUs") %>
  4. </ul>

This will render the list items and put a class=”current” attribute on the one for the page currently being viewed.

Now an obvious problem with this approach is that you can’t embed sub menus (ULs within LIs). The way around this is to mimic the MVC framework itself and introduce new BeginListItem and EndListItem methods (ASP.NET MVC has BeginForm and EndForm).

  1. public static string BeginListItem(this HtmlHelper helper, string linkText, string actionName,string controllerName)
  2. {
  3.     string result;
  4.  
  5.     TagBuilder builder = GetListItem(helper, linkText, actionName, controllerName);
  6.     result = builder.ToString(TagRenderMode.StartTag);
  7.     result += builder.InnerHtml;
  8.  
  9.     return result;
  10. }

This opens the li tag. The EndListItem method closes it.

  1. public static void EndListItem(this HtmlHelper helper)
  2.         {
  3.             HttpResponseBase httpResponse = helper.ViewContext.HttpContext.Response;
  4.             httpResponse.Write("</li>");
  5.         }

And we can use these methods as follows.

  1. <%= Html.BeginListItem("Contact Us", "Index", "ContactUs")%>
  2.     <ul>
  3.         <%= Html.ListItem("Find Us", "Index", "FindUs")%>                   
  4.     </ul>
  5. <% Html.EndListItem(); %>

Next Time

Up next is how to spice this menu up and make it all “interactivy” using JQuery,

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.