Mocking generic method call for any given type parameter
With Moq 4.13 or later you can use
It.IsAnyType
— matches any typeIt.IsSubtype<T>
— matches T and proper subtypes of TIt.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);