Assigning out/ref parameters in Moq

C#ParametersMoqRefOut

C# Problem Overview


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.

C# Solutions


Solution 1 - C#

For 'out', the following seems to work for me.

public interface IService
{
	void DoSomething(out string a);
}

[TestMethod]
public void Test()
{
	var service = new Mock<IService>();
	var expectedValue = "value";
	service.Setup(s => s.DoSomething(out expectedValue));

	string actualValue;
	service.Object.DoSomething(out actualValue);
	Assert.AreEqual(expectedValue, actualValue);
}

I'm guessing that Moq looks at the value of 'expectedValue' when you call Setup and remembers it.

For ref, I'm looking for an answer also.

I found the following QuickStart guide useful: https://github.com/Moq/moq4/wiki/Quickstart

Solution 2 - C#

Moq version 4.8 (or 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).

Solution 3 - C#

EDIT: In Moq 4.10, you can now pass a delegate that has an out or ref parameter directly to the Callback function:

mock
  .Setup(x=>x.Method(out d))
  .Callback(myDelegate)
  .Returns(...); 

You will have to define a delegate and instantiate it:

...
.Callback(new MyDelegate((out decimal v)=>v=12m))
...

For Moq version before 4.10:

Avner Kashtan provides an extension method in his blog which allows setting the out parameter from a callback: Moq, Callbacks and Out parameters: a particularly tricky edge case

The solution is both elegant and hacky. Elegant in that it provides a fluent syntax that feels at-home with other Moq callbacks. And hacky because it relies on calling some internal Moq APIs via reflection.

The extension method provided at the above link didn't compile for me, so I've provided an edited version below. You'll need to create a signature for each number of input parameters you have; I've provided 0 and 1, but extending it further should be simple:

public static class MoqExtensions
{
    public delegate void OutAction<TOut>(out TOut outVal);
    public delegate void OutAction<in T1,TOut>(T1 arg1, out TOut outVal);

    public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, TOut>(this ICallback<TMock, TReturn> mock, OutAction<TOut> action)
        where TMock : class
    {
        return OutCallbackInternal(mock, action);
    }

    public static IReturnsThrows<TMock, TReturn> OutCallback<TMock, TReturn, T1, TOut>(this ICallback<TMock, TReturn> mock, OutAction<T1, TOut> action)
        where TMock : class
    {
        return OutCallbackInternal(mock, action);
    }

    private static IReturnsThrows<TMock, TReturn> OutCallbackInternal<TMock, TReturn>(ICallback<TMock, TReturn> mock, object action)
        where TMock : class
    {
        mock.GetType()
            .Assembly.GetType("Moq.MethodCall")
            .InvokeMember("SetCallbackWithArguments", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock,
                new[] { action });
        return mock as IReturnsThrows<TMock, TReturn>;
    }
}

With the above extension method, you can test an interface with out parameters such as:

public interface IParser
{
    bool TryParse(string token, out int value);
}

.. with the following Moq setup:

    [TestMethod]
    public void ParserTest()
    {
        Mock<IParser> parserMock = new Mock<IParser>();

        int outVal;
        parserMock
            .Setup(p => p.TryParse("6", out outVal))
            .OutCallback((string t, out int v) => v = 6)
            .Returns(true);

        int actualValue;
        bool ret = parserMock.Object.TryParse("6", out actualValue);

        Assert.IsTrue(ret);
        Assert.AreEqual(6, actualValue);
    }



Edit: To support void-return methods, you simply need to add new overload methods:

public static ICallbackResult OutCallback<TOut>(this ICallback mock, OutAction<TOut> action)
{
    return OutCallbackInternal(mock, action);
}

public static ICallbackResult OutCallback<T1, TOut>(this ICallback mock, OutAction<T1, TOut> action)
{
    return OutCallbackInternal(mock, action);
}

private static ICallbackResult OutCallbackInternal(ICallback mock, object action)
{
    mock.GetType().Assembly.GetType("Moq.MethodCall")
        .InvokeMember("SetCallbackWithArguments", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock, new[] { action });
    return (ICallbackResult)mock;
}

This allows testing interfaces such as:

public interface IValidationRule
{
    void Validate(string input, out string message);
}

[TestMethod]
public void ValidatorTest()
{
    Mock<IValidationRule> validatorMock = new Mock<IValidationRule>();

    string outMessage;
    validatorMock
        .Setup(v => v.Validate("input", out outMessage))
        .OutCallback((string i, out string m) => m  = "success");

    string actualMessage;
    validatorMock.Object.Validate("input", out actualMessage);

    Assert.AreEqual("success", actualMessage);
}

Solution 4 - C#

This is documentation from Moq site:

// out arguments
var outString = "ack";
// TryParse will return true, and the out argument will return "ack", lazy evaluated
mock.Setup(foo => foo.TryParse("ping", out outString)).Returns(true);


// ref arguments
var instance = new Bar();
// Only matches if the ref argument to the invocation is the same instance
mock.Setup(foo => foo.Submit(ref instance)).Returns(true);

Solution 5 - C#

Seems like it is not possible out of the box. Looks like someone attempted a solution

See this forum post http://code.google.com/p/moq/issues/detail?id=176

this question https://stackoverflow.com/questions/726630/verify-value-of-reference-parameter-with-moq

Solution 6 - C#

Building on Billy Jakes awnser, I made a fully dynamic mock method with an out parameter. I'm posting this here for anyone who finds it usefull.

// Define a delegate with the params of the method that returns void.
delegate void methodDelegate(int x, out string output);

// Define a variable to store the return value.
bool returnValue;

// Mock the method: 
// Do all logic in .Callback and store the return value.
// Then return the return value in the .Returns
mockHighlighter.Setup(h => h.SomeMethod(It.IsAny<int>(), out It.Ref<int>.IsAny))
  .Callback(new methodDelegate((int x, out int output) =>
  {
    // do some logic to set the output and return value.
    output = ...
    returnValue = ...
  }))
  .Returns(() => returnValue);

Solution 7 - C#

I'm sure Scott's solution worked at one point,

But it's a good argument for not using reflection to peek at private apis. It's broken now.

I was able to set out parameters using a delegate

      delegate void MockOutDelegate(string s, out int value);

    public void SomeMethod()
    {
        ....

         int value;
         myMock.Setup(x => x.TryDoSomething(It.IsAny<string>(), out value))
            .Callback(new MockOutDelegate((string s, out int output) => output = userId))
            .Returns(true);
    }

Solution 8 - C#

To return a value along with setting ref parameter, here is a piece of code:

public static class MoqExtensions
{
    public static IReturnsResult<TMock> DelegateReturns<TMock, TReturn, T>(this IReturnsThrows<TMock, TReturn> mock, T func) where T : class
        where TMock : class
    {
        mock.GetType().Assembly.GetType("Moq.MethodCallReturn`2").MakeGenericType(typeof(TMock), typeof(TReturn))
            .InvokeMember("SetReturnDelegate", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, mock,
                new[] { func });
        return (IReturnsResult<TMock>)mock;
    }
}

Then declare your own delegate matching the signature of to-be-mocked method and provide your own method implementation.

public delegate int MyMethodDelegate(int x, ref int y);

    [TestMethod]
    public void TestSomething()
    {
        //Arrange
        var mock = new Mock<ISomeInterface>();
        var y = 0;
        mock.Setup(m => m.MyMethod(It.IsAny<int>(), ref y))
        .DelegateReturns((MyMethodDelegate)((int x, ref int y)=>
         {
            y = 1;
            return 2;
         }));
    }

Solution 9 - C#

I struggled with this for an hour this afternoon and could not find an answer anywhere. After playing around on my own with it I was able to come up with a solution which worked for me.

string firstOutParam = "first out parameter string";
string secondOutParam = 100;
mock.SetupAllProperties();
mock.Setup(m=>m.Method(out firstOutParam, out secondOutParam)).Returns(value);

The key here is mock.SetupAllProperties(); which will stub out all of the properties for you. This may not work in every test case scenario, but if all you care about is getting the return value of YourMethod then this will work fine.

Solution 10 - C#

I struggled with many of the suggestions here before I simple created an instance of a new 'Fake' class that implements whatever interface you are trying to Mock out. Then you can simply set the value of the out parameter with the method itself.

Solution 11 - C#

In VS2022 you can simply do:

foo.Setup(e => e.TryGetValue(out It.Ref<ExampleType>.IsAny))
.Returns((ref ExampleType exampleType) => {
exampleType = new ExampleType();
return true;
})

Solution 12 - C#

The following is an example that is working.

[Fact]
public void DeclineLowIncomeApplicationsOutDemo()
{
    var mockValidator = new Mock<IFrequentFlyerNumberValidator>();

    var isValid = true; // Whatever we set here, thats what we will get.

    mockValidator.Setup(x => x.IsValid(It.IsAny<string>(), out isValid));

    var sut = new CreditCardApplicationEvaluator(mockValidator.Object);

    var application = new CreditCardApplication
    {
        GrossAnnualIncome = 19_999,
        Age = 42
    };

    var decision = sut.EvaluateUsingOut(application);

    Assert.Equal(CreditCardApplicationDecision.AutoDeclined, decision);
}

public interface IFrequentFlyerNumberValidator
{
    bool IsValid(string frequentFlyerNumber);
    void IsValid(string frequentFlyerNumber, out bool isValid);
}

Note there is no Returs in the setup as there is no returns.

Solution 13 - C#

This can be a solution .

[Test]
public void TestForOutParameterInMoq()
{
  //Arrange
  _mockParameterManager= new Mock<IParameterManager>();

  Mock<IParameter > mockParameter= new Mock<IParameter >();
  //Parameter affectation should be useless but is not. It's really used by Moq 
  IParameter parameter= mockParameter.Object;

  //Mock method used in UpperParameterManager
  _mockParameterManager.Setup(x => x.OutMethod(out parameter));

  //Act with the real instance
  _UpperParameterManager.UpperOutMethod(out parameter);

  //Assert that method used on the out parameter of inner out method are really called
  mockParameter.Verify(x => x.FunctionCalledInOutMethodAfterInnerOutMethod(),Times.Once());
  
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRichard SzalayView Question on Stackoverflow
Solution 1 - C#Craig CelesteView Answer on Stackoverflow
Solution 2 - C#stakx - no longer contributingView Answer on Stackoverflow
Solution 3 - C#Scott WegnerView Answer on Stackoverflow
Solution 4 - C#KosauView Answer on Stackoverflow
Solution 5 - C#GishuView Answer on Stackoverflow
Solution 6 - C#MartijnView Answer on Stackoverflow
Solution 7 - C#Billy Jake O'ConnorView Answer on Stackoverflow
Solution 8 - C#Victor MukherjeeView Answer on Stackoverflow
Solution 9 - C#maxshutyView Answer on Stackoverflow
Solution 10 - C#Casey O'BrienView Answer on Stackoverflow
Solution 11 - C#Red Riding HoodView Answer on Stackoverflow
Solution 12 - C#VivekDevView Answer on Stackoverflow
Solution 13 - C#FabriceView Answer on Stackoverflow