Search code examples
moqpex

Do Pex and Moq work together nicley?


Has anyone tried this?

I like moq and i like what pex is doing, but haven't tried them together. I'd prefer to use moq over moles in most cases I think but am curious to see if anyone has hit roadblocks?

Do they play nice?


Solution

  • Although I haven't tried, Pex and Moq should get along like old friends.

    While the interception techniques between Pex and Moq are different (Pex uses the ProfilerAPI to interpret MSIL instructions; Moq uses DynamicProxy to dynamically derive classes) there are references in the Moq source code that suggest it was designed to prevent re-entrance problems where Pex would interfere with Moq.

    According to the original research paper for Pex, you can decorate your code with attributes that control when the Pex rewriter is used.

    From the Moq source code:

    internal static MethodCall<T> Setup<T>(Mock mock, Expression<Action<T>> expression, Func<bool> condition) where T : class
    {
        return PexProtector.Invoke(() =>
        {
           var methodCall = expression.ToMethodCall();
           var method = methodCall.Method;
           var args = methodCall.Arguments.ToArray();
           ThrowIfNotMember(expression, method);
           ThrowIfCantOverride(expression, method);
    
           var call = new MethodCall<T>(mock, condition, expression, method, args);
           var targetInterceptor = GetInterceptor(methodCall.Object, mock);
           targetInterceptor.AddCall(call, SetupKind.Other);
    
           return call;
         });   
     }
    

    PexProtector is defined as:

     internal sealed class __ProtectAttribute : Attribute
     {
     }
    
     namespace Moq
     {
        [__Protect]
        [DebuggerStepThrough]
        internal static class PexProtector
        {
            public static void Invoke(Action action)
            {
               action();
            }
    
            public static T Invoke<T>(Func<T> function)
            {
               return function();
            }
        }
     }