RichP's Blog

The .Net ramblings of Richard Penrose

Archive for the ‘Unit Testing’ Category

NMock – Custom List Matcher

without comments

I am a big believer in Test Driven development. I am also an avid user of mocking Frameworks I having used the excellent Rhino Mocks framework in the past and am currently using the NMock framework as this is the preference of my current client.

Anyway, the other day I was testing some code was struggling to work out how to test it effectively. The code that I was trying to test is shown below:

[sourcecode language='c#']
public interface IDataGateway
{
int AddMessageToQueue(Message message, IList customerIds);
}

public class MessageHandler
{
private IDataGateway _dataGateway;
public MessageHandler(IDataGateway dataGateway)
{
_dataGateway = dataGateway;
}

public int SendMessage(Message message, IList customerIds)
{
IList newCustomerIds = customerIds.ToList().ConvertAll(c => int.Parse(c));
int messageCount = _dataGateway.AddMessageToQueue(message, newCustomerIds);
return messageCount;
}
}
[/sourcecode]

The code above is fairly simple. I won’t discuss ways to improve it as it is really designed to illustrate a point.

As I am a Mockist I would like to test that given an input message and list of customer ids the AddMessageToQueue method on the _dataGateway object is called with the correct parameters.

NMock can help me with this because it allows me to Mock the _dataGateway interface and then inspect the interactions between my MessageHandler object and _dataGateway. The problem is that I can’t test this interaction in the bog standard NMock way because my I have no control over the newCustomerIds list that is created inside this method. Enter the Custom Matcher.

So, I developed a custom list matcher and used this to help define the expectation on the _dataGateway mock. The code is listed below:

[sourcecode language='c#']
public class ListMatcher : Matcher
{
private IList _theList;

public ListMatcher() : this(null)
{
}

public ListMatcher(IList theList)
{
_theList = theList;
}

public override void DescribeTo(System.IO.TextWriter writer)
{
writer.Write(“< ");
writer.Write(this.GetType().Name);
writer.Write(">“);
}

public override bool Matches(object o)
{
bool itMatches = false;
List inList = o as List;
if ((inList != null) && inList.Count == _theList.Count)
{
itMatches = true;
for (int i = 0; i < _theList.Count; i++)
{
itMatches = itMatches && _theList[i].ToString() == inList[i].ToString();
}
}

return itMatches;
}
}
[/sourcecode]

This list matcher allows NMock to compare the elements of two lists. You pass the expected list into the constructor on instantiation and this is used to compare against a list passed in a method call.

The code snippet below shows how to wire up the unit test.

[sourcecode language='c#']
[Test]
public void SendMessage_ExpectCorrectInteractions()
{
Mockery mockery = new Mockery();
IDataGateway dataGateway = mockery.NewMock();

MessageHandler handler = new MessageHandler(dataGateway);

Message message = new Message();
List customerIds = new List(new string[] { “1″, “2″, “3″ });
List expectedCustomerIds = new List(new int[] { 1, 2, 3 });

Expect.Once.On(dataGateway).Method(“AddMessageToQueue”).
With(Is.EqualTo(message), new ListMatcher(expectedCustomerIds)).Will(Return.Value(6));

handler.SendMessage(message, customerIds);

mockery.VerifyAllExpectationsHaveBeenMet();
}
[/sourcecode]

That’s it really, hope that this proves useful to somebody!

Written by admin

March 10th, 2010 at 1:23 pm

Posted in Unit Testing