Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callback and Returns: Allow callback parameters to have type object where a type matcher was used #953

Closed
stakx opened this issue Oct 19, 2019 · 2 comments · Fixed by #992
Milestone

Comments

@stakx
Copy link
Contributor

stakx commented Oct 19, 2019

Example:

mock.Setup(m => m.Method(It.IsAny<string>(), It.IsAny<It.IsAnyType>(), It.IsAny<int>())
    .Callback((string arg1, object arg2, int arg3) => ...);

which is arguably more user-friendly than having the following (which we have today):

mock.Setup(m => m.Method(It.IsAny<string>(), It.IsAny<It.IsAnyType>(), It.IsAny<int>())
    .Callback(IInvocation invocation => ...);
@stakx
Copy link
Contributor Author

stakx commented Apr 5, 2020

What on earth was I thinking when I opened this issue? It gets just about everything backwards.

mock.Setup(m => m.Method(It.IsAny<string>(), It.IsAny<It.IsAnyType>(), It.IsAny<int>())
    .Callback((string arg1, object arg2, int arg3) => ...);

This already works today, no change needed.

mock.Setup(m => m.Method(It.IsAny<string>(), It.IsAny<It.IsAnyType>(), It.IsAny<int>())
    .Callback(IInvocation invocation => ...);

This doesn't work; at least not for .Returns. For .Callback, the lambda can optionally be wrapped in an InvocationAction; for .Returns, the lambda must be wrapped in an InvocationFunc. The latter requirement could be relaxed, then we could probably mark Invocation{Action,Func} as obsolete.

@stakx
Copy link
Contributor Author

stakx commented Apr 5, 2020

[...] then we could probably mark Invocation{Action,Func} as obsolete.

No, we cannot do that, at least not for InvocationFunc. There are some scenarios, such as this one, where it isn't possible to make the compiler happy (except perhaps through use of dynamic):

public interface IX
{
    T void M<T>(T arg);
}

var xMock = new Mock<IX>();
xMock.Setup(x => x.M(It.IsAny<It.IsAnyType>())).Returns((IInvocation invocation) =>
{
    // ...
    return ?;
});

In the above example, the lambda's return type is fixed to It.IsAnyType by the signature of Returns, and it's impossible for the lambda to actually return a value of that type. In such cases, you'd have to go the more untyped route of .Returns(new InvocationFunc(invocation => ...)).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant