Schubert's Blog

A biker and technology enthusiast's
view of the world

Mapze.com and TDD & Mocks Part 1

This is my first foray into the world of writing code to test other code and have to admit, I enjoyed it. Ever since, I have tried to use TDD in every project, even if it only means testing a subset of the desired functionality. The finalized Mapze.com Beta 1 website had 490 test cases, 243 to test the Business logic layer, 121 to test the MVC Controllers and 126 to test the helper classes. The only disadvantage of TDD I've found so far is it almost doubles the development time. But the confidence of knowing that the website can cope with all the test cases, thought up during and after development, outweighs the cons.

In this blog entry, I'll discuss the BlBase class, Mapze.com's base business logic class and cover how I've gone about using NUnit and Rhino Mocks to test it in the next blog entry. Having decided to use LinqToSql as the Data Access Layer, all the business logic classes will need an instance of the data context. They will also need an instance of the current user to carry out selects, inserts and updates against. Making the BlBase class look like:

public class BlBase
{
//Current user variable, all business logic code have access to the current user
public IUser currentUser;
//The datacontext initialised once per request
public RedStartDataContext currentDataContext;

//Only for testing, inject a fake user identity
public static IIdentity FakeIUser;
//Modelstate dictionary, all business logic code can store
//informative and error messages here
public ModelStateDictionary currentModelState;
...

The BlBase class has one constructor and no methods. And this constructor has code to intialise the current user and data context variable. The constructor looks like:

  ...
//Constructor to initialise the user and data context
public BlBase(ModelStateDictionary ModelState, IUserService UserService)
{
//save the model state and initialise the data context
currentModelState = ModelState;
currentDataContext = new RedStartDataContext();

//Get the current user

//A little trick here: when this code is live
//HttpContext.Current will never be null. When
//NUnit call this code the FakeIUser will be used
//instead. Mapze Beta 2 has a cleaner implementation.
IIdentity identity;
if (HttpContext.Current != null)
identity = HttpContext.Current.User.Identity;
else
identity = FakeIUser;

//is the request authenticated
if (identity.IsAuthenticated)
{
//get the user from db
currentUser = UserService.Get(identity.Name);

//Make sure there is a user with the identity name
//also make sure the user account is not suspended.
//The 1 in the ModelError is picked up by a custom
//MVC error trapping filter and logs out the user.
if(currentUser == null || currentUser.Suspended)
{
currentModelState.AddModelError("SevereError", 1);
}
}
}
}

I believe most social networking and user interactive website will have a similar base class for all their business logic classes to inherit from. Making sure this class works correctly is of utmost importance, especially to business that rely on their user base for sales and feedback. The next blog entry shows how I've used NUnit and Rhino Mocks to test this class.