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; } }
Exactly what I was looking for!
Thank you ;)