将同步Moq模拟转换为异步

时间:2012-08-22 21:28:50

标签: c# moq async-await

我正在努力将同步asp.net代码的主体转换为.net 4.5和新的异步语法。

我有很多看起来像的测试代码:

var retVal = new Foo(bar,baz);
_myMock.Setup(x => x.DoSomething(123)).Returns(retVal);

当我将DoSomething的签名从Foo DoSomething()转换为async Task<Foo> DoSomething()时,我的所有测试代码都必须重写。我目前的解决方法是将原始代码转换为:

var retVal = new Foo(bar,baz);
_myMock.Setup(x => x.DoSomething(123))
   .Returns(new Task<Foo>(()=>retVal));

这不是一个特别难的转换,但是当我有数千个需要更新的测试时,这很乏味。

我尝试使用一个名为ReturnsAsync的扩展方法来执行某些形式的m,但我遇到了一些我无法确定的类型推理问题。是否有一种标准或更简单的方法来转换这种模拟以更好地处理异步方法?

2 个答案:

答案 0 :(得分:35)

首先,命名:基于任务的异步模式(TAP)表示所有异步并返回Task的方法应该以{{1​​}}结尾。因此,您的方法应命名为Async

其次,DoSomethingAsync的构造函数创建了一个未启动的Task,您必须手动Task。如果您的实际Start()方法也执行此操作,那么这也不会遵循TAP,这意味着您的代码将无法与DoSomething一起使用。相反,您应该使用await,或者更好的Task.Run(() => value)

第三,如果你向我们展示你的代码不能正常工作会更好,这样我们就能告诉你你在哪里犯了错误。

现在,Task.FromResult(value)扩展方法的主体非常简单,但我的大部分工作都是找出正确的类型(特别是因为我不知道Moq)。代码如下所示:

ReturnsAsync()

答案 1 :(得分:21)

Moq 4.2添加了ReturnsAsync()扩展方法,因此您不再需要添加自己的方法。