Fun with Moq: Dynamic mocking

Run time mocking

Sometimes it’s useful to be able to create a Mock object without the type being known at compile time. Normally when using Moq you create a Mock object using this syntax:

var mock = new Mock<IMyInterface>().Object;

But what if IMyInterface is not known at compile time? What you would like would be to do this var mock = new Mock(myType).Object and receive the mocked object back. Turns out this method does not exists, but it’s possible to get around this using the magic of reflection!

public static object DynamicMock(Type type)
   var mock = typeof(Mock<>).MakeGenericType(type).GetConstructor(Type.EmptyTypes).Invoke(new object[] { });
   return mock.GetType().GetProperties().Single(f => f.Name == "Object" && f.PropertyType == type).GetValue(mock, new object[] {});

This piece of code will return to you a mock that implements the interface type you specify and return it as an object. This could then be used for various fun stuff to automate the unit testing of certain things.

Dynamic parameter checking

Seen this code before?

public class MyConcreteClass 
   private readonly IDependency1 _a;
   private readonly IDependency2 _b;
   private readonly IDependency1 _c;
   private readonly IDependency1 _d

   public MyConcreteClass(IDependency1 a, IDependency2 b, IDependency1 c, IDependency1 d)
     if (a == null) throw new ArgumentNullException("a");
     if (b == null) throw new ArgumentNullException("b");
     if (c == null) throw new ArgumentNullException("c");
     if (d == null) throw new ArgumentNullException("d");

     _a = a;
     _b = b;
     _c = c;
     _d = d;

It’s great to cast all those ArgumentNullExceptions to check the value, but testing this is a complete pain, since you’d need four separate test cases for each parameter to verify that the correct exception is being thrown. With dynamic mocking and some reflection this can be totally automated for classes that only take interfaces as parameters – which in a heavily dependency injected application is pretty much all of them.

All you need to test this scenario is a single call to NullParameterCheck<MyConcreteClass>() and this method somewhere in your testing code.

public static void NullParameterCheck<T>()
	var constructor = typeof(T).GetConstructors().Single();

	Assert.IsFalse(constructor.GetParameters().Any(f => !f.ParameterType.IsInterface), "All parameters must be interfaces in order to use this helper");

	for (int i = 0; i< constructor.GetParameters().Length; ++i)
		var paramName = constructor.GetParameters()[i].Name;
		int i1 = i;
		var args = constructor.GetParameters().Select((p, ix) => ix == i1
			? null
			: DynamicMock(p.ParameterType));
			Assert.Fail("No exception for parameter null {0}", paramName);
		catch (TargetInvocationException e)
			Assert.IsTrue(e.InnerException is ArgumentNullException);
			Assert.AreEqual(paramName, ((ArgumentNullException)e.InnerException).ParamName);

This code will loop around each parameter, replacing one of them with null in turn to verify that each interface parameter will generate the corresponding ArgumentNullException

Happy mocking!

Tagged , , , ,

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: