ReturnAsync的Moq回调

时间:2015-08-06 08:56:28

标签: c# asp.net-mvc unit-testing asynchronous moq

我目前正在为异步操作重构API,我需要重构异步测试。我的情况类似于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());

我需要将其更改为:

// 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());

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

1 个答案:

答案 0 :(得分:3)

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

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

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

在第二个示例中,您将值0传递给ReturnsAsync方法,这就是模拟每次返回零的原因。虽然ReturnsAsync不支持传递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());