Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning out parameters in Moq for methods that return void

In this question, I found an this answer that seems to be the best way to solve the problem to me.

The provided code assumes that the function that is mocked returns a value:

bool SomeFunc(out ISomeObject o);

However, the object I want to mock has an out function as follows:

void SomeFunc(out ISomeObject o);

The relevant code fragment from the mentioned answer:

public delegate void OutAction<TOut>(out TOut outVal);

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

Void is not a valid type for TReturn. So I believe I would have to somehow adapt this code to get it to work with methods returning void. But how?

like image 924
Wilbert Avatar asked Nov 18 '13 11:11

Wilbert


1 Answers

Maybe you simply need this:

ISomeObject so = new SomeObject(...);
yourMock.Setup(x => x.SomeFunc(out so));

Then when you use yourMock.Object in the code you test, the so instance will "magically" come out as the out parameter.

It is a little non-intuitive ("out is in"), but it works.


Addition: Not sure I understand the scenario. The following complete program works fine:

static class Program
{
  static void Main()
  {
    // test the instance method from 'TestObject', passing in a mock as 'mftbt' argument
    var testObj = new TestObject();

    var myMock = new Mock<IMyFaceToBeTested>();
    IMyArgFace magicalOut = new MyClass();
    myMock.Setup(x => x.MyMethod(out magicalOut)).Returns(true);

    testObj.TestMe(myMock.Object);
  }
}

class TestObject
{
  internal void TestMe(IMyFaceToBeTested mftbt)
  {
    Console.WriteLine("Now code to be tested is running. Calling the method");
    IMyArgFace maf; // not assigned here, out parameter
    bool result = mftbt.MyMethod(out maf);
    Console.WriteLine("Method call completed");
    Console.WriteLine("Return value was: " + result);
    if (maf == null)
    {
      Console.WriteLine("out parameter was set to null");
    }
    else
    {
      Console.WriteLine("out parameter non-null; has runtime type: " + maf.GetType());
    }
  }
}

public interface IMyFaceToBeTested
{
  bool MyMethod(out IMyArgFace maf);
}
public interface IMyArgFace
{
}
class MyClass : IMyArgFace
{
}

Please indicate how your situation is different, by using the names of the classes and interfaces from my example.

like image 188
Jeppe Stig Nielsen Avatar answered Sep 25 '22 02:09

Jeppe Stig Nielsen