Archive for the ‘Unit Testing’ Category
Reading and Listing Embedded Files
When writing unit tests I occasionally find the need to include embedded resources (mostly files – e.g. XML). This enables the tests to run anywhere without relying on a specific file structure. Each time I do this I seem to have to re-create the same test utility for managing these files so I thought I’d pop the code on my blog:
Here is some sample code:
public class EmbededResourceHelper
{
public static string ReadEmbededResourceFile(string path)
{
var text = string.Empty;
using (var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream(path))
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
reader.Close();
}
return text;
}
public static byte[] ReadEmbededResourceFileAsBytes(string path)
{
byte[] bytes;
using (var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream(path))
{
bytes = ReadFully(stream);
}
return bytes;
}
private static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
public static void ListEmbededResources()
{
Assembly.GetExecutingAssembly()
.GetManifestResourceNames().ToList()
.ForEach(x => Debug.WriteLine(x));
}
}
NMock – Custom List Matcher
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:
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;
}
}
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:
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; } }
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.
[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();
}
That's it really, hope that this proves useful to somebody!