Moq callback for ReturnsAsync

I am currently refactoring an API for asynchronous actions and I need to refactor my tests for async. I have a 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 since ReturnAsync()

it doesn't support lambda yet, the callback is called, but apparently in a different context, and hence the variable remains the value for the next call instead of incrementing. Is there a way to solve this problem?

+3


source to share


1 answer


In the first example, you are passing a lambda to a method Returns

, and that lambda is reevaluated every time the mock method is called. Because of this, you can combine Callback

andReturns

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 to the method ReturnsAsync

, so it must return zero every time. Although ReturnsAsync

does not support transmission Func

, you can still use Returns

like this

var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThingAsync())
    .Returns(() => Task.FromResult(calls++));

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

      

+3


source







All Articles