Deq: Extend your favorite Mock framework with Moles

 

This post shows how you can leverage the un-typed Detours API to extend any mock framework
to support static methods, sealed types, etc…

Moles is an isolation
framework for .NET that the Pex team
designed to make Pex happy. It relies heavily on delegates and comes with a syntax
of its own. Moles is actually a simple strongly typed layer on top of a un-typed general
purpose detour API. If you do not like the Moles syntax, you can still leverage the
detours API to deal with static methods or sealed types.

Let us see how we can use the detour API to build a micro-mock-framework using expressions
trees. Let’s call it Deq.

The Challenge

As usual, we’ll toy with an example where we need a very particular DateTime.Now value.
Since DateTime.Now is a struct living in mscorlib.dll, it cannot be mocked using traditional
approaches –DateTime.Now can’t be overloaded. The test case looks like this and will
most likely fail.

image The
Whish

We would like to be able to replace the implementation of DateTime.Now with a method
that always returns the year 2000 in the context of the test. If possible, we would
like to use a strongly typed, Linq-ish, expression tree based syntax to do this. For
example, we could think that a Deq class would define a Replace(Expression<Func<T>>
method, Func<T> detour)
method that would achieve this detour:

image

 Implementing Deq on top of MoleRuntime

The implementation of Deq.Replace relies on MoleRuntime.SetMole,
an un-typed API to replace methods that Moles builds upon. First, one needs to walk
the expression tree to extract the MethodInfo that the user wanted to replace (I’m
not showing this code here, it is beyond the point of this blog post). Once you have
the method, you can use the Moles API to install the detour. This happens through
the MoleRuntime.SetMole method and the rest is taken care of the
Moles runtime.

imageThat’s
it. You’ve just written a micro-mock framework that can isolate from static methods.

To get this code to compile, you will need a reference to Microsoft.ExtendedReflection.dll
and Microsoft.Moles.Framework.dll. Also, since the Replace method only works for the
Func<T> method, you’ll probably want to write a T4 template that takes care
of all the other delegates (Func<T,T2>, Action<…> etc…).

Deq Sources?

The Deq sources are available in the Samples solution that ships with Pex.