ReturnsAsync 的起订量回调

And*_*ree 6 c# asp.net-mvc unit-testing asynchronous moq

我目前正在将 API 重构为异步操作,并且需要重构异步测试。我有与Moq 文档中类似的情况:

// 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());
Run Code Online (Sandbox Code Playgroud)

我需要将其更改为:

// 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());
Run Code Online (Sandbox Code Playgroud)

但由于ReturnAsync()还不支持 lambda,回调被调用,但显然是在不同的上下文中,因此变量仍然是下一次调用的值而不是增加。有办法解决这个问题吗?

Mat*_*ole 5

在第一个示例中,您将 lambda 传递给该Returns方法,并且每次调用模拟方法时都会重新评估该 lambda。正因为如此,你实际上可以结合CallbackReturns

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

Console.WriteLine(mock.Object.GetCountThing());
Run Code Online (Sandbox Code Playgroud)

在第二个示例中,您将值 0 传递到ReturnsAsync方法中,这就是模拟每次都返回零的原因。虽然ReturnsAsync不支持传递 a Func,但您仍然可以Returns像这样使用

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

Console.WriteLine(await mock.Object.GetCountThingAsync());
Run Code Online (Sandbox Code Playgroud)