Useful Moq Extension Method
I have been working with ASP .NET MVC and I use the Moq mocking library to help test the code I write. Often in ASP MVC anonymous objects are passed around as function arguments. This is especially common in calls to RouteUrl. Since I want to be able to test this and verify that it is called correctly I wrote a handy extension method to make it easier called AsMatch.
To be able to test the UrlHelper (since it doesn't have an interface or virtual methods) I wrote a simple wrapper around it with an interface to enable testing. Using that with this extension method makes testing route generation a breeze.
Given a call to generate a Url like this:
var url = Url.RouteUrl("Show", new { projectName="matt" });
You can write a setup on your Mock of the Url helper using a similar syntax:
UrlHelperMock
.Setup(x => x.RouteUrl("Show",new{ projectName="matt"}.AsMatch()))
.Return("someUrlToTest");
Here is the code that defines the AsMatch extension method:
public static class ObjectMoqExtensions
{
public static object AsMatch(this object @object)
{
return Match<object>.Create(testObject => DoObjectsMatch(@object, testObject));
}
private static bool DoObjectsMatch(object object1, object object2)
{
var props1 = ToDictionary(object1);
var props2 = ToDictionary(object2);
var query = from prop1 in props1
join prop2 in props2 on prop1.Key equals prop2.Key
select prop1.Value.Equals(prop2.Value);
return query.Count(x => x) == Math.Max(props1.Count(), props2.Count());
}
public static Dictionary<string, object> ToDictionary(object @object)
{
var dictionary = new Dictionary<string, object>();
var properties = TypeDescriptor.GetProperties(@object);
foreach (PropertyDescriptor property in properties)
dictionary.Add(property.Name, property.GetValue(@object));
return dictionary;
}
}