Thursday 5 March 2009

Testing that a method has been called with Rhino Mocks and the WhenCalled method

I find that sometimes it’s necessary to test that one method calls another.  This is particularly useful when implementing the Object Method pattern to wrap up an object in a static class to allow more simple calls to the object than by using the singleton pattern.  For example I have a logging class called LogIt;

public static class LogIt
   {
       // Object method pattern.
       #region Object Method Pattern
       static ILogger _Logger;
 
       /// <summary>
       /// Initialise method, must be called by every public static method.
       /// </summary>
       private static void Initialise()
       {
           if (_Logger == null)
           {
               _Logger = new EntLibLogger();
           }
       }
 
       /// <summary>
       /// Override the logger instance with another instance of the interface.
       /// </summary>
       /// <param name="logger"></param>
       public static void OverrideInstance(ILogger logger)
       {
           _Logger = logger;
       } 
       #endregion
 
       public static void Info(string message)
       {
           Initialise();
           throw new NotImplementedException();
       }
}

And I want to test the Info method.  The info method’s only responsibility is to call ILogger’s Info(string, callingmethod) method, so this is the only thing I need to test for.  Here is one way to test it with Rhino Mocks.  If you are reading this and you know a better way, I’d love to hear it.

Here is my test initialiser, I’m using MSTest for these tests.

[TestInitialize()]
public void InitialiseTest()
{
    MockRepository mocks = new MockRepository();
    ILogger logger = mocks.StrictMock<ILogger>();
    _CallCount = 0;
 
    using (mocks.Record())
    {
        Expect
            .Call(delegate
            {
                logger.Error("", null);
            }).IgnoreArguments()
            .WhenCalled(delegate 
            {
                _CallCount++;
            })
            .Repeat.AtLeastOnce();
    }
 
    LogIt.OverrideInstance(logger);
}

This code tells the mocking framework that when we call Logger.Error(arguments) to increment the _CallCount.  Now our test can check the call count after the call.

/// <summary>
///A test for Error
///</summary>
[TestMethod()]
public void ErrorTest()
{
    LogIt.Error("Test");
    Assert.AreEqual(1, _CallCount);
}

There must be plenty of ways to do this and the example above is just the most simple way I could come up with when using Rhino Mocks.

No comments: