Mocking generic method call for any given type parameter

With Moq 4.13 or later you can use

  • It.IsAnyType — matches any type
  • It.IsSubtype<T> — matches T and proper subtypes of T
  • It.IsValueType — matches only value types

To get the value of the generic argument or do some other operation with the original method, you can use IInvocation parameter of InvocationAction or InvocationFunc

  • setup.Callback(new InvocationAction(invocation => ...))
  • setup.Returns(new InvocationFunc(invocation => ...))

Here is an example:

var myMock = new Mock<IDataProvider>();
myMock.Setup(m => m.GetDataDocument<It.IsAnyType>(It.IsAny<Guid>())).Returns(new InvocationFunc(invocation =>
{
    var type = invocation.Method.GetGenericArguments()[0];
    return Activator.CreateInstance(type);
}));

Instead of using a mock, maybe your case would be better to use a Stub.

public class StubDataProvider : IDataProvider
{
    public T GetDataDocument<T>(Guid document) where T : class, new()
    {
        return new T();
    }
}

If you truly need a mock (so you can verify that GetDataDocument was called). Instead of trying to wrestle with a Mocking framework it sometimes is easier to just create a Mock class out right.

public class MockDataProvider : IDataProvider
{
    private readonly Action _action;

    public MockDataProvider(Action action)
    {
        _action = action;
    }

    public T GetDataDocument<T>(Guid document) where T : class, new()
    {
        _action();
        return new T();
    }
}

And than in your test:

bool wasCalled = false;
IDataProvider dataProvider = new MockDataProvider(() => { wasCalled = true; });
var aTable = dataProvider.GetDataDocument<ATable>(new Guid());
Debug.Assert(wasCalled);

Tags:

C#

Moq