Q:

Moq callback for ReturnsAsync

I'm currently refactoring API to async actions and I need to refactor the tests for async. I have similar case as in the Moq documentation:
// returning different values on each invocation
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThing())
    .Returns(() => calls)
    .Callback(() => calls++);
// returns 0 on first invocation, 1 on the next, and so on
Console.WriteLine(mock.Object.GetCountThing());

And I need to change it to:
// returning different values on each invocation
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThingAsync())
    .ReturnsAsync(calls)
    .Callback(() => calls++);
// returns 0 on first invocation, 1 on the next, and so on
Console.WriteLine(mock.Object.GetCountThingAsync());

But as the ReturnAsync() doesn't support lambda yet, the callback is called, but apparently in different context and thus the variable remains the value for the next call instead of being increased. Is there a way how to solve this?

A:

In the first example you are passing a lambda to the Returns method, and that lambda is re-evaluated each time the mocked method is called. Because of this, you can actually combine Callback and Returns
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThing())
    .Returns(() => calls++);

Console.WriteLine(mock.Object.GetCountThing());

In the second example you are passing the value 0 into the ReturnsAsync method, so that is why the mock returns zero each time. Although ReturnsAsync doesn't support passing a Func, you can still use Returns like so
var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThingAsync())
    .Returns(() => Task.FromResult(calls++));

Console.WriteLine(await mock.Object.GetCountThingAsync());

