Friday 24 October 2008

Unit Testing the Enterprise Library #2 - Unit Testing the Caching Application Block

Unit testing the caching application block for my project was a little different from the logging application block.  There was no reason to test my own custom cache manager and for the part of my tests I have assumed that the enterprise library functions as expected and does not require unit testing.  What I must then unit test is that I am correctly consuming the application block into my code.

In my code I have a class that is responsible for storing and retrieving cache objects.  All my objects are stored using a key object with an overridden ToString() method like so.

class CacheKey
{
    /// <summary>
    /// Must be an object that uniquely identifies itself thorugh ToString (like int or string).
    /// </summary>
    public object Key { get; set; }
 
    /// <summary>
    /// The type of the object stored.
    /// </summary>
    public Type ObjectType { get; set; }
 
    public CacheKey()
    {
    }
 
    /// <summary>
    /// Override constructor to pass in the parameters.
    /// </summary>
    /// <param name="key">The key for the object</param>
    /// <param name="objectType">The type of the object</param>
    public CacheKey(object key, Type objectType)
    {
        Key = key;
        ObjectType = objectType;
    }
 
    /// <summary>
    /// This override will cat together the key and the type into a string to reference the object
    /// in the cache uniquely.
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        if (Key == null)
        {
            throw new System.ArgumentNullException("Key");
        }
 
        if (ObjectType == null)
        {
            throw new System.ArgumentNullException("ObjectType");                
        }
 
        if (Key.ToString().Trim().Length == 0)
        {
            throw new System.ArgumentOutOfRangeException("Key");
        }
 
        return (ObjectType.ToString() + "." + Key.ToString());
    }
}

My Caching class will create the key via the index and object type like so:

public void UpdateCache(object key, object toCache, CacheManager manager)
{
    CacheKey cacheKey = new CacheKey(key, toCache.GetType());
 
    // Cache managers are stored against the toString output of the CacheManager enum.
    ICacheManager cacheManager = CacheFactory.GetCacheManager(manager.ToString());
    cacheManager.Add(cacheKey.ToString(), toCache);
}

And retrieve it by object type and key in much the same way.

For unit testing, all I had to do was add some items to the cache and then check the cache directly to ensure that my class had put them where they need to be.  Here is a subset of my test cases.  Firstly to test the update of data in the cache:

// Create an object to cache.
string cacheObject = "cached string";
string identifier = "1";
EntLibCache cache = new EntLibCache();
 
// Test for the default cache using multiple different objects with specific Ids.
cache.UpdateCache(identifier, cacheObject, CacheManager.Default);
string defaultCacheManager = CacheManager.Default.ToString();
ICacheManager cacheManager = CacheFactory.GetCacheManager(defaultCacheManager);
CacheKey cacheKey = new CacheKey(identifier, cacheObject.GetType());
string returnFromCache = (string)cacheManager.GetData(cacheKey.ToString());
Assert.AreEqual(cacheObject, returnFromCache);

And then test the retrieval of data from the cache:

EntLibCache target = new EntLibCache();
 
// Add a bunch of objects to the cache.
int key1 = 1;
string value1 = "one";
int key2 = 1;
int value2 = 1234;
int key3 = 3;
string value3 = "three";
 
// Put the values in the cache.
target.UpdateCache(key1, value1, CacheManager.Default);
target.UpdateCache(key2, value2, CacheManager.Default);
target.UpdateCache(key3, value3, CacheManager.User);
 
Assert.AreEqual(value1, (string)target.GetObject(key1, value1.GetType(), CacheManager.Default));
Assert.AreEqual(value2, (int)target.GetObject(key2, value2.GetType(), CacheManager.Default));
Assert.AreEqual(value3, (string)target.GetObject(key3, value3.GetType(), CacheManager.User));

It’s that simple.  Not all of my test cases are here, no point posting all my code, but they follow these lines fairly well.  In my case I use an enum to specify the cache manager and use the ToString method to turn it into the string representation that is required by the cache manager, thus keeping strong typing in my code.

You will have to be sure to edit the app.config of your test class to add the cache managers you need or your tests will fall over.

Blogger Label Cloud Widget

I had considered moving to another blogging tool because I didn’t think that blogger had enough of the things I liked about blogs.  One of those things is a label cloud.  Well since then I found this post by Seige.  It outlines how to install a label cloud, similar to the one I’ve got in my sidebar now.

This coupled with the Windows Live Writer is part of the reason I think I’ll stick with blogger for now.

Thursday 23 October 2008

Posting with Windows Live Writer

So I thought I’d try posting with windows live writer to see how it goes, this is my first post.  I’m not sure if this tool is useful yet, but it seems like it would be.

Most specifically I want to be able to post my code more easily.

   1: class CatchIt
   2: {
   3:     UpdateCache
   4: }

Looks like it does a really good job doesn’t it?

One thing you should know about it though.  You’ll have to download a plugin to allow for easy code posting.  You can do this on the right hand panel, just click “Add a Plug-in…”.  Also if your posts come up with your code separated by extra lines, you can remove that by setting your blogger “Convert line breaks” setting under settings / formatting.

Unit Testing the Enterprise Library #1 - Unit Testing the Logging Application Block

So I've decided that using the enterprise library in my application is a great idea. We're also following TDD and I'm using a design pattern called Object Method to abstract the implementation of my framework classes from my application. But I've come across a problem. When I'm unit testing my implementation I find that it's very difficult to unit test the implementation of the Enterprise Library. Then I came across this article by Mark Seemann showing how to unit test the Logging Application block. It's very simple really, you create a custom logging trace listener in your test project and have the custom listener store all log messages in a list you can unit test later. What the article was not specific about was the implementation of the enterprise library in your test project. If you add an app.config file to your test project then your test library will load the config settings from the test project's app.config file. Add your custom block to the test project and add the trace listener to the "All Events" section and it should work just fine. So for example, this is Mark Seemann's custom trace listener:
   1: ///
   2: /// This is a custom trace listener that loads the trace information into a
   3: /// list of entries in the log file.
   4: /// Found here: http://blogs.msdn.com/ploeh/archive/2006/04/06/UnitTestYourEnterpriseLibraryLoggingLogic.aspx
   5: /// Author: Mark Seemann
   6: ///
   7: [ConfigurationElementType(typeof(CustomTraceListenerData))]
   8: public class StubTraceListener : CustomTraceListener
   9: {
  10:     private readonly static List logEntries_ = new List();
  11:     private readonly static List logMessages_ = new List();
  12:     
  13:     public override void Write(string message)
  14:     {
  15:         StubTraceListener.logMessages_.Add(message);
  16:     }
  17:     
  18:     public override void WriteLine(string message)
  19:     {
  20:         StubTraceListener.logMessages_.Add(message);
  21:     }
  22:     
  23:     public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
  24:     {
  25:          LogEntry le = data as LogEntry;
  26:         
  27:          if (le != null)
  28:          {
  29:              StubTraceListener.logEntries_.Add(le);
  30:         
  31:              if (this.Formatter != null)
  32:              {
  33:                  this.Write(this.Formatter.Format(le));
  34:                  return;
  35:              }
  36:          }
  37:         
  38:          base.TraceData(eventCache, source, eventType, id, data);
  39:     }
  40:     
  41:     internal static IList GetLogMessages()
  42:     {
  43:          return new ReadOnlyCollection(StubTraceListener.logMessages_);
  44:     }
  45:     
  46:     internal static IList GetLogEntries()
  47:     {
  48:          return new ReadOnlyCollection(StubTraceListener.logEntries_);
  49:     }
  50:     
  51:     internal static void Reset()
  52:     {
  53:          StubTraceListener.logEntries_.Clear();
  54:          StubTraceListener.logMessages_.Clear();
  55:     }
  56: }
And here is my test case:
   1: [TestMethod()]
   2: public void WarningTest()
   3: {
   4:     EntLibLogger target = new EntLibLogger();
   5:     string message = "warning message";
   6:     LogPriority priority = LogPriority.Low;
   7:     CallingMethod callingMethod = new CallingMethod();
   8:     
   9:     target.Warning(message, priority, callingMethod);
  10:     IList entries = StubTraceListener.GetLogEntries();
  11:     
  12:     Assert.IsNotNull(entries);
  13:     Assert.AreEqual(1, entries.Count);
  14:     Assert.AreEqual((int)priority, entries[0].Priority);
  15:     Assert.AreEqual(message, entries[0].Message);
  16: }

I'm not testing much, but you can extend your test cases to test as much as you need. Just make sure you have an app.config file in your test project liks so:

And that you've used the LAB to setup your custom trace listener:

Tuesday 14 October 2008

Microsoft Enterprise Library #5 – Cache Management

So I had a look into the caching applicaiton block and was impressed with some of the things that it could do. After this I went on a practical use adventure in which I hit a couple of road blocks, so I thought I'd blog about them. In this case I came across a problem where for each object I'm referencing by key I need to setup a new Cache Manager in the application block. If I have to do this for each object I wish to cache I'm going to have a very large cache config file that I don't really want to have to manage. So here is how I got around it. I created a Key class that held the unique information about my object.

class CacheKey
{
 public object Id {get;set;}
 public Type {get;set;}

 public override string ToString()
 {
  return type.ToString() + "." + id.ToString();
 }
}
In my cache interface I have methods to create a generic cached object like so.

interface ICache
{
 void UpdateCache(object key, object objectToCache);

 void UpdateCache(object key, object objectToCache, CacheManager manager);

 object GetObjectFromCache(object key, Type objectType);

 object GetObjectFromCache(object key, Type objectType, CacheManager manager);
}
So in my implementation I would do the following.

public void UpdateCache(object key, object objectToCache)
{
 CacheKey keyObj = new CacheKey();
 keyObj.Id = key.ToString();
 keyObj.Type = objectToCache.GetType();
 
 ICacheManager defaultCache = CacheFactory.GetCacheManager("DefaultManager");
 defaultCache.Add(keyObj.ToString(), objectToCache);
}

object GetObjectFromCache(object key, Type objectType)
{
 CacheKey keyObj = new CacheKey();
 keyObj.Id = key;
 keyObj.Type = objectType;

 object returnObject = userCache.GetData(keyObj.ToString());
}
If I want to handle multiple managers then I just pass through the manager to the methods from the interface when I implement them. This allows me to use the same rule for every object in the default cache without setting up a specific rule for each object I want to cache. There are some disadvantages to this method. I wouldn't recommend that you use this for large volumes of data as it could slow down your cache. Keep large volumes in their own rules, I.E. for postal codes (or zip codes for americans), you don't want searching throuh the possible zip codes to find your logged in user details to slow you down.

Friday 10 October 2008

TDD - Testing Static Methods with the Method Object Pattern

I'm a big fan of TDD and unit testing in general, but there are some things that come with it that can often make life difficult. A tightly coupled applicaiton can be increadibly difficult to unit test. If you implement a logger that uses the enterprise library and you don't want to spawn up the entire library so that you can do a simple test you're going ot have a little bit of difficulty. In fact if you use any static methods that tightly couple tools to the rest of your code then you're going to find unit testing your kind of like trying to chew through your own neck. (makes a funny image doesn't it?) In our new applicaiton we want implementation to be simple. Static methods are often useful when you have stateless code (like our logger) and the implementation is easy (Logger.Log("message");) but testing is disasterously hard. To get around this we are implementing the Method Object pattern. I love patterns, when making design decisions it's nice to say: "We've followed this pattern, and this pattern and this design framework" and know that someone before you has at least thought of it enough to put it down on paper, but don't get bogged down. Just because it's a pattern doesn't mean it's good. At least in this case, I think it is. The Method Object pattern is almost common sense. When I say "I want to use TDD with static methods" after I sift out the abusive comments and weed out the "You're doing it wrong!" idealists I'm left with some good advice. A singleton is one option, programming to an interface and defining an object is another, a service provider is also a good idea. The best one I've come across is the Method Object pattern. See this code:

public class Logger
{
  public static void Info(string message)
  {
      // Implementation specific code
  }
}
This code is almost impossible to test. It is tightly coupling the application with the logging framework I choose to implement. Method Object will specify that my static class is an API shell calling an instance of an object, which now becomes a static object singleton. My code becomes:

public interface ILogger
{
  void Info(string message);
  void Debug(string message);
}

public class EntLibLogger : ILogger
{
  public void Info(string message)
  {
      // Implementation specific code
  }
}

public class Logger
{
  private static ILogger _Logger = new EntLibLogger();

  public static void OverrideInstance(ILogger logger)
  {
      _Logger = logger;
  }
}
And all of a sudden I can mock out my Logging framework using Rhino Mocks (or whatever mocking framework takes your fancy) and still use static methods in my code with loose coupling. Here is my test code. I'm testing a class with a method called Remove that takes a string. It logs some info and I don't want it to fail because the enterprise library isn't instanciated. I'm using Rhino Mocks to create a mock object of the interface and the OverrideInstance method to setup my mocked logger as the current logger.

public void RemoveTest()
{
  MockRepository mocks = new MockRepository();
  ILogger logger = mocks.CreateMock();
  Logger.OverrideInstance(logger);
  Stock target = new Stock();
  string remove = "id";
  target.Remove(remove);
}
So there you go. I think this is a good method for testing static functions if you feel they would be helpful to your applicaiton.

Wednesday 8 October 2008

Microsoft Enterprise Library #4 – Cache Application Block

At first glance there wasn't anything useful in the Cache Application Block. As we delved further into the requirements of our project I've found that there are many things that we would like to keep at hand and not have go delve off into the database to retrieve. But is the Cache application block worth my time to use? If it saves on retrieval time for data objects that I would like to keep handy then it is definitely worth while. Even it it removes the need to perform a transaction against the database that will be heavily utilised it will be worth while.

My Requirements

For my Requirements I have a very simple task.

  1. Cache the user that I've loaded from the database using the Entity Framework
  2. Reload that user at any time
  3. Expire the user after 60 seconds
  4. Perform a particular action when the user's cache expires

I could use membership to do a similar task, but if I'm not using membership (like if I use Windows authentication), then this may be useful. There are lots of other ways to do this I'm aware, but this will show off the cache application block using a simple scenario.

Step 1 - Setup the block

I added the DLL Files that I needed. Again Vikas Goyal has a good tutorial on this one here and I used this to help setup the config files that I need and get an idea on how the block works. I used an ASP.NET MVC project as that is the tool we will be going with, but you don't need to use one if you prefer something else. Next I opened the web.config (or app.config in winforms) with the enterprise library config tool and added the config application block to my project. I want to cache the logged in user's details so I added a new cache manager and called it UserManager. I set the poll frequency to 10 seconds because I want my timeout to be 60 seconds or there about but left the rest as default. I should be done now.

Step 2 - Create My Cache Object

I've got my simple class:

namespace EntLibCABDemo.Models
{
 public class UserDetails
 {
    public String UserName { get; set; }
    public String State { get; set; }
    public String EmailAddress { get; set; }
 }
}

Step 3 - Implement the Cache

So now I'm going to create a new action for viewing the data in the cache. If the action doesn't find the data in the cache it will display a message telling me that it has re-created it, otherwise it will display the data. If I refresh the page after 60 seconds it should let me know it has re-created it. I created a CreateUser action to create the user with the code below. The SlidingTime specifies that every time I access the object that it will restart the timer. Once created, we'll redirect to the view method.

public ActionResult CreateUser()
{
 Models.UserDetails user = new Models.UserDetails();
 user.UserName = "Steve";
 user.EmailAddress = "Steve@company.com";
 user.State = "NSW";
 
 ICacheManager userCache = CacheFactory.GetCacheManager("UserManager");
 userCache.Add(user.UserName, user, CacheItemPriority.Normal,
     null, new SlidingTime(TimeSpan.FromSeconds(60)));
 
 return Redirect("ViewUser");
}

And then a ViewUser to view the user. Here we get the user from the cache and setup the view data with a string to display.

public ActionResult ViewUser()
{
 ICacheManager userCache = CacheFactory.GetCacheManager("UserManager");
 Models.UserDetails user = (Models.UserDetails)userCache.GetData("Steve");
 
 if (user == null)
 {
     // Not found, tell the user.
     ViewData["Message"] = "No current user found for 'Steve'";
 }
 else
 {
     // Found, set the string.
     ViewData["Message"] = "Found Steve: " + user.State + " " + user.EmailAddress;
 }
 
 return View("User");
}

Then the view to display the user, just getting the view data and spitting it out to the screen.

Details: <%=Html.Encode(ViewData["Message"])%>

And I'm ready to test, Lo and behold it works. Hitting the create method will return the view and show the user's details "Found Steve: NSW Steve@company.com". If I leave it 60 seconds and refresh the view I get "No current user found for 'Steve'". If I refresh before the 60 seconds is up the cache restarts the timeout and I get another 60 seconds of time.

Step 4 - Handling Events on Expiration

Now I want to handle an event when the content expires. All I need to do is create a class that implements the ICacheItemRefreshAction interface and set it when I add the item. To test it, when the user expires I'll change the email address and reset it in the cache.

public class RefreshCache : ICacheItemRefreshAction
{
  public void Refresh(string removedKey, object expiredValue,
      CacheItemRemovedReason removalReason)
  {
      UserDetails user = (UserDetails)expiredValue;
      user.EmailAddress = "new@company.com";
      CacheFactory.GetCacheManager("UserManager").Add(removedKey, user);
  }
}

That's it. When testing, after 60 seconds the cache expired and fired the event. The user was set back into the cache and when I refreshed the page the email address changed from Steve@company.com to new@company.com.

Final Thoughts

The Cache Application Block is very simple and works very well from all my first tests. I can't think of a reason not to use it. We will be using it to cache items from the database and file system information that we don't want to continually reload.