Search code examples
c#parametersmoqrefout

Assigning out/ref parameters in Moq


Is it possible to assign an out/ref parameter using Moq (3.0+)?

I've looked at using Callback(), but Action<> does not support ref parameters because it's based on generics. I'd also preferably like to put a constraint (It.Is) on the input of the ref parameter, though I can do that in the callback.

I know that Rhino Mocks supports this functionality, but the project I'm working on is already using Moq.


Solution

  • Moq version 4.8 and later has much improved support for by-ref parameters:

    public interface IGobbler
    {
        bool Gobble(ref int amount);
    }
    
    delegate void GobbleCallback(ref int amount);     // needed for Callback
    delegate bool GobbleReturns(ref int amount);      // needed for Returns
    
    var mock = new Mock<IGobbler>();
    mock.Setup(m => m.Gobble(ref It.Ref<int>.IsAny))  // match any value passed by-ref
        .Callback(new GobbleCallback((ref int amount) =>
         {
             if (amount > 0)
             {
                 Console.WriteLine("Gobbling...");
                 amount -= 1;
             }
         }))
        .Returns(new GobbleReturns((ref int amount) => amount > 0));
    
    int a = 5;
    bool gobbleSomeMore = true;
    while (gobbleSomeMore)
    {
        gobbleSomeMore = mock.Object.Gobble(ref a);
    }
    

    The same pattern works for out parameters.

    It.Ref<T>.IsAny also works for C# 7 in parameters (since they are also by-ref).