Moq: How to get to a parameter passed to a method of a mocked service
You can use the Mock.Callback-method:
var mock = new Mock<Handler>();
SomeResponse result = null;
mock.Setup(h => h.AsyncHandle(It.IsAny<SomeResponse>()))
.Callback<SomeResponse>(r => result = r);
// do your test
new Foo(mock.Object).Bar(22);
Assert.NotNull(result);
If you only want to check something simple on the passed in argument, you also can do it directly:
mock.Setup(h => h.AsyncHandle(It.Is<SomeResponse>(response => response != null)));
The Callback method will certainly work, but if you are doing this on a method with a lot of parameters it can be a bit verbose. Here is something that I have used to remove some of the boilerplate.
var mock = new Mock<Handler>();
// do your test
new Foo(mock.Object).Bar(22);
var arg = new ArgumentCaptor<SomeResponse>();
mock.Verify(h => h.AsyncHandle(arg.Capture()));
Assert.NotNull(arg.Value);
Here is the source for ArgumentCaptor:
public class ArgumentCaptor<T>
{
public T Capture()
{
return It.Is<T>(t => SaveValue(t));
}
private bool SaveValue(T t)
{
Value = t;
return true;
}
public T Value { get; private set; }
}
An alternative is to use Capture.In
, which is an out-of-the-box feature in Moq that lets you capture arguments into a collection:
//Arrange
var args = new List<SomeResponse>();
mock.Setup(h => h.AsyncHandle(Capture.In(args)));
//Act
new Foo(mock.Object).Bar(22);
//Assert
//... assert args.Single() or args.First()
Gamlor's answer worked for me, but I thought I would expand on John Carpenter's comment because I was looking for a solution involving more than one parameter. I figured other folks who stumble onto this page may be in a similar situation. I found this info in the Moq documentation.
I'll use Gamlor's example, but let's pretend the AsyncHandle method takes two arguments: a string
and a SomeResponse
object.
var mock = new Mock<Handler>();
string stringResult = string.Empty;
SomeResponse someResponse = null;
mock.Setup(h => h.AsyncHandle(It.IsAny<string>(), It.IsAny<SomeResponse>()))
.Callback<string, SomeResponse>((s, r) =>
{
stringResult = s;
someResponse = r;
});
// do your test
new Foo(mock.Object).Bar(22);
Assert.AreEqual("expected string", stringResult);
Assert.IsNotNull(someResponse);
Basically you just need to add another It.IsAny<>()
with the appropriate type, add another type to the Callback
method, and change the lambda expression as appropriate.